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

Macro expansion #102

Open
anderejd opened this issue Apr 23, 2020 · 11 comments
Open

Macro expansion #102

anderejd opened this issue Apr 23, 2020 · 11 comments
Labels
enhancement New feature or request help wanted Extra attention is needed important If you want to contribute, please consider this issue before others.

Comments

@anderejd
Copy link
Contributor

Add macro expansion of some kind. Perhaps directly using cargo expand or doing something similar.

@anderejd anderejd added enhancement New feature or request help wanted Extra attention is needed labels Apr 23, 2020
@mxxo
Copy link

mxxo commented Apr 24, 2020

Hi! I think this would 100% take care of the plutonium issue.
For functions like:

#[safe]
unsafe fn real_safe(x: f32) -> i32 {
    std::mem::transmute::<f32, i32>(x)
}

#[safe]
fn deref_null() {
    let p = &mut 0 as *mut i32;
    println!("{}", *p);
}

If you call expand, you get something like this:

fn real_safe(x: f32) -> i32 {
    #[allow(unused_unsafe)]
    unsafe {
        std::mem::transmute::<f32, i32>(x)
    }
}
fn deref_null() {
    #[allow(unused_unsafe)]
    unsafe {
        let p = &mut 0 as *mut i32;
        // etc  ....
    }
}

So I think the regular function visitor can handle it after expansion.
I don't think the disclaimer where the expanded code /= actual code applies here, but maybe it's just something to watch out for.

@Shnatsel
Copy link

Turns out there is a way to leverage rustc to detect all uses of unsafe code without requiring nightly: https://www.reddit.com/r/rust/comments/g9mw57/oneliner_to_correctly_list_all_uses_ofunsafe_in/

My quick tests show that it does in fact detect unsafe code in macros.

@anderejd
Copy link
Contributor Author

anderejd commented Apr 29, 2020

Looks promising! Anyone who reads this and want to add it or something similar to cargo-geiger, please go ahead :)

EDIT: As in go ahead and send a PR ;)

@eddyb
Copy link

eddyb commented Apr 29, 2020

As a quick explanation, the pieces are:

  • passing -vv to Cargo means that it will use --cap-lints=warn instead of --cap-lints=allow, so that you can get lints from dependencies without having to run rustc yourself
    • the otherwise redundant --cap-lints=warn in RUSTFLAGS means that crates in the current workspace will also get the same behavior, so that no fatal errors will be caused by lints
  • --message-format=json allows you to parse and filter Cargo/rustc messages
    • I use jq in the example but you'd likely use serde_json from Rust, ofc
    • the rendered field gives you full user-friendly rustc output, so no information is lost
    • you also get more details about the source location in JSON, even a full macro backtrace, so you can do more interesting statistics
  • -Funsafe-code in RUSTLAGS forces the lint you're looking for
    • this generalizes to any rustc or even clippy lints
    • -D (deny) and -W (warn) are equivalent given --cap-lints=warn, but my hope was that -F (forbid) couldn't be overridden by #[allow(unsafe_code)] in the Rust code, as usually forbid isn't, but I haven't confirmed this
      • it's possible --cap-lints=warn replaces -F with -W eagerly, which we might want to fix in rustc if that's the case

@anderejd anderejd added the important If you want to contribute, please consider this issue before others. label May 2, 2020
@8573
Copy link

8573 commented Jun 19, 2020

I well may be misunderstanding something, but it occurs to me that expanding a proc macro means executing arbitrary code, potentially allowing an adversarial proc macro to hide unsafe by messing with the running cargo-geiger process (edit: or merely not emitting unsafe if it sees that cargo-geiger is running). (Of course there are worse things it could do, but I suppose those aren't the focus of this ticket.)

(The state of cargo-sandbox is unfortunate.)

@carbotaniuman
Copy link

The adversarial proc-macro can already hide unsafe code currently though, so we're no better off, and I given that some proc macros do legitimately use unsafe code that should be audited, I think the benefits are worth it.

@tarcieri
Copy link
Collaborator

Yeah, a more straightforward scenario is a proc macro that detects it's being run under cargo-geiger and emits one set of code in that scenario without unsafe, but otherwise would use unsafe

@8573
Copy link

8573 commented Oct 21, 2020

It occurs to me to speculate (idly) that cargo-geiger itself could try to hide from proc-macros, maybe by changing its process name to (e.g.) "cargo-make" and (where available) using bind-mount trickery to hide .travis.yml etc. if these mention "geiger" ... I'm not suggesting this should be a development priority. :-)

@Shnatsel
Copy link

Then we would be engaging in an arms race with attackers, except attackers know our single exact set of behaviors and we know nothing about the attackers. This is doomed from the start.

@carbotaniuman
Copy link

I was mainly addressing macro expansion for things like the old proposal for cxx or stuff wrapping unsafe operations like pin_mut, not to protect against stuff like plutonium (which I really don't have a problem with).

@anderejd
Copy link
Contributor Author

Slightly related to #69, since #69 will replace the cargo crate with cargo as a subprocess.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed important If you want to contribute, please consider this issue before others.
Projects
None yet
Development

No branches or pull requests

7 participants