Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean unsafe in unsafe fns warnings #348

Merged
merged 3 commits into from
Jun 4, 2021
Merged

Conversation

ojeda
Copy link
Member

@ojeda ojeda commented Jun 4, 2021

Requesting a review from our in-house Rust experts since even if this is mechanical, I am not 100% sure I know about all the cases where introducing a block may change behavior (e.g. creating temporaries etc.).

Note that this does not add // SAFETY comments -- that cleanup will come later when we add a tidy script, but this at least cleans up the warnings to avoid missing other warnings in the sea and allows us to deny the warning so that we stop getting new unsafe blocks inside unsafe fns without a proper // SAFETY comment.

Fixes #340.
Fixes #341.

ojeda added 3 commits June 4, 2021 19:23
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
This prevents new ones from getting in.

Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
@ojeda ojeda requested review from alex, nbdd0121 and bjorn3 June 4, 2021 17:33
@ksquirrel
Copy link
Member

Review of a0ea20f07a50:

  • ⚠️ This PR changes more than 20 files.
  • ✔️ Commit c606d85: Looks fine!
  • ✔️ Commit f81ade8: Looks fine!
  • ✔️ Commit a0ea20f: Looks fine!

Copy link
Member

@nbdd0121 nbdd0121 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, as long as CI passes.

Does the CI cover all Rust files?

@ojeda
Copy link
Member Author

ojeda commented Jun 4, 2021

LGTM, as long as CI passes.

Well, that was super quick! Please do not rush it! :)

Does the CI cover all Rust files?

Good question, if they are not, well, soon people will notice since it is deny :)

@ojeda
Copy link
Member Author

ojeda commented Jun 4, 2021

By the way, to simplify, I have not split some of the unsafes into several lines etc. (which should be done).

I will open an issue and explain what should be done to do the tidy cleanup (basically removing the unsafe, checking what the compiler says, then adding as needed).

@TheSven73
Copy link
Collaborator

Do we need to switch on some sort of "warnings=errors" in the build? As part of this PR, or a new one?

@ojeda
Copy link
Member Author

ojeda commented Jun 4, 2021

Do you mean making the warning now an error? It is done in the third commit.

@TheSven73
Copy link
Collaborator

TheSven73 commented Jun 4, 2021

Should we go even further, and treat all warnings as errors?

@ojeda
Copy link
Member Author

ojeda commented Jun 4, 2021

For rust/ code, 100% with being super strict.

For the rest of modules etc., I would also do it -- if we deny instead of forbid, they can still workaround it if needed.

Copy link
Member

@bjorn3 bjorn3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are no behavior changes I think.

@@ -85,8 +85,11 @@ impl<T: Sync> FileOpenAdapter for Registration<T> {
type Arg = T;

unsafe fn convert(_inode: *mut bindings::inode, file: *mut bindings::file) -> *const Self::Arg {
// TODO: `SAFETY` comment required here even if `unsafe` is not present,
// because `container_of!` hides it. Ideally we would not allow
// `unsafe` code as parameters to macros.
let reg = crate::container_of!((*file).private_data, Self, mdev);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The macro could introduce a temp outside of the unsafe block that stores the value casted to a raw ptr. Ideally no $foo:expr happen inside an unsafe block for macros.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1, opening an issue.

Copy link
Member Author

@ojeda ojeda Jun 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this could also be a lint with some logic like:

  • If inside an unsafe fn...
  • And there is a macro call outside an unsafe block...
  • And unsafe_op_in_unsafe_fn is enabled in this context...
  • And if the node/AST/tree of a parameter appears as-is...
  • Then check that node/AST/tree is not inside an introduced unsafe block.

Easier said than done, and I guess I am forgetting a few things, but... :^)

If you think it makes sense, I can open an issue too.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe. I believe there has been discussion previously regarding "unsafe" hygiene, but I can't remember what came of it. I think it was on internals.rust-lang.org.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it does not hurt to open it to keep track.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -111,7 +111,7 @@ pub trait ModuleParam: core::fmt::Display + core::marker::Sized {
///
/// The `arg` field of `param` must be an instance of `Self`.
unsafe extern "C" fn free(arg: *mut crate::c_types::c_void) {
core::ptr::drop_in_place(arg as *mut Self);
unsafe { core::ptr::drop_in_place(arg as *mut Self) };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and elsewhere you may want to move the ; inside the unsafe block. While this doesn't change behavior as all cases are for () returning expressions I think, it does look nicer IMHO.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, now that you mention it, I agree.

Does anyone know if there a way to tell rustfmt to look for this? Or in Clippy perhaps?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't find a clippy lint for this. Makes sense to have as a clippy lint though IMO.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ojeda
Copy link
Member Author

ojeda commented Jun 4, 2021

Thanks a lot @bjorn3 and @nbdd0121!

Let me merge as is, since you both reviewed it -- we can change style later (e.g. in the tidy cleanup round).

@ojeda ojeda merged commit cae4454 into Rust-for-Linux:rust Jun 4, 2021
@ojeda ojeda deleted the warnings branch June 4, 2021 19:12
@nbdd0121
Copy link
Member

nbdd0121 commented Jun 4, 2021

Should we go even further, and treat all warnings as errors?

#![deny(warnings)] is generally considered as an anti-pattern, see here. We could use RUSTFLAGS="-D warnings" (we currently call it RUSTCFLAGS) in the CI, but it shouldn't be in the Makefile.

@TheSven73
Copy link
Collaborator

TheSven73 commented Jun 4, 2021

(edited out a wordy reply that basically just agrees with Gary, lol)

So yes, I would be on board with switching on "deny warnings" in the CI only, not in the Makefile.

@ojeda
Copy link
Member Author

ojeda commented Jun 4, 2021

I was referring more to deny individually as many warnings as possible, like this one, i.e. not every possible future warning. So agreed!

ojeda pushed a commit that referenced this pull request Jun 11, 2024
Add a test case to assert that the skb->pkt_type which was set from the BPF
program is retained from the netkit xmit side to the peer's device at tcx
ingress location.

  # ./vmtest.sh -- ./test_progs -t netkit
  [...]
  ./test_progs -t netkit
  [    1.140780] bpf_testmod: loading out-of-tree module taints kernel.
  [    1.141127] bpf_testmod: module verification failed: signature and/or required key missing - tainting kernel
  [    1.284601] tsc: Refined TSC clocksource calibration: 3408.006 MHz
  [    1.286672] clocksource: tsc: mask: 0xffffffffffffffff max_cycles: 0x311fd9b189d, max_idle_ns: 440795225691 ns
  [    1.290384] clocksource: Switched to clocksource tsc
  #345     tc_netkit_basic:OK
  #346     tc_netkit_device:OK
  #347     tc_netkit_multi_links:OK
  #348     tc_netkit_multi_opts:OK
  #349     tc_netkit_neigh_links:OK
  #350     tc_netkit_pkt_type:OK
  Summary: 6/0 PASSED, 0 SKIPPED, 0 FAILED

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/r/20240524163619.26001-4-daniel@iogearbox.net
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
5 participants