-
Notifications
You must be signed in to change notification settings - Fork 29
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
offset_of
is unsound
#9
Comments
Actually, |
This already goes wrong in practice on aarch64. I compiled the example below with use memoffset::offset_of;
struct Foo {
foo: i32,
}
fn main() {
println!("foo: {}", offset_of!(Foo, foo));
} The result of running the compiled binary on a Raspberry Pi 3B is that it hits a
A stacktrace with lldb:
Compiled using
|
That probably has the |
Indeed, it's compiled with the |
Btw, another way in which this is unsound is that it does not protect against auto-deref: Something like |
@Gilnaa btw, see this thread on IRLO for a version of the macro that fixes most of these problems. The comment about references to uninitialized data being okay is incorrect though, but they currently cannot be avoided until the lang team makes progress on rust-lang/rfcs#2582. This macro doesn't work in |
I'll try to take care of it over the weekend. I apologise for the delay. |
AFAICT, there's no way to currently implement this correctly.
Why is that? Isn't it a valid reference to an invalid T? |
@Gilnaa By "valid reference" here I mean that the answer to both questions in rust-lang/unsafe-code-guidelines#77:
is "yes". (Answering both "yes" renders "valid reference to an invalid T" a contradiction in terms) |
I see. |
It doesn't. That's why I said above that implementing However, with |
One of the reasons we want it to be UB is that some people ask that a function like But that means |
I've removed the unsound impl and yanked the affected version from crates.io |
Thanks! The remaining impl is also still unsound. If you wait until Thursday, you can make it use a version with And probably, on old rustc the following is safer than let base_ptr: &$father = NonNull::dangling().as_ref();
let field_ptr = &base_ptr.$field;
let offset = (field_ptr as *const _ as usize) - (base_ptr as *const _ as usize) This way at least we only materialize bad references and perform an incorrect offset operations, instead of materializing bad values of any type. Do you have any ideas for fixing the problem with auto-deref? TBH I am not sure if the API you want (that supports any number of nested fields) can be implemented correctly. And I am not talking about UB here, I am talking about: struct S { x: u32 };
type Father = Box<S>;
let offset = offsetof!(Father, x); // *oops* |
I don't think anyone is actually using the nested field syntax, but it's probably pretty easy to check. |
Humm, it seems as if $ rg from_ptr!
discord_game_sdk/mock/src/instance.rs
46: from_ptr!(Instance, from_core, sys::IDiscordCore, interfaces.core);
47: from_ptr!(Instance, from_application, sys::IDiscordApplicationManager, interfaces.applications);
48: from_ptr!(Instance, from_user, sys::IDiscordUserManager, interfaces.users);
49: from_ptr!(Instance, from_image, sys::IDiscordImageManager, interfaces.images);
50: from_ptr!(Instance, from_activity, sys::IDiscordActivityManager, interfaces.activities);
51: from_ptr!(Instance, from_relationship, sys::IDiscordRelationshipManager, interfaces.relationships);
52: from_ptr!(Instance, from_lobby, sys::IDiscordLobbyManager, interfaces.lobbies);
53: from_ptr!(Instance, from_network, sys::IDiscordNetworkManager, interfaces.networking);
54: from_ptr!(Instance, from_overlay, sys::IDiscordOverlayManager, interfaces.overlay);
55: from_ptr!(Instance, from_storage, sys::IDiscordStorageManager, interfaces.storage);
56: from_ptr!(Instance, from_store, sys::IDiscordStoreManager, interfaces.store);
57: from_ptr!(Instance, from_voice, sys::IDiscordVoiceManager, interfaces.voice);
58: from_ptr!(Instance, from_achievement, sys::IDiscordAchievementManager, interfaces.achievements); |
Hello! I can probably update to not use the nested function anymore, I might have the time to do that tomorrow. Thank you for checking which libraries would be affected though! |
Oh, this is probably the reason why |
Wait. Wouldn't forcing the |
What is the concrete proposal? |
Declare a |
But which implementation do you want to use in the Not sure how I feel about that... UB during CTFE can't really propagate to run-time, at least currently. However, we reserve the right to make CTFE complain loudly and fail if your const-code causes UB. I consider the fact that such code does not error a bug. So, your code would basically not be subject to Rust's stability guarantee. (That's my interpretation, anyway.) |
Should this not be kept open until the soundness issue is resolved entirely (and not just the exploitable UB)? |
Also, I have not looked closely at |
I think spanof originally used offsetof and it probably still can |
This includes a security update in a transitive dependency: Gilnaa/memoffset#9
This includes a security update in a transitive dependency: Gilnaa/memoffset#9
The latest release includes the `--ignore` feature we use, so upgrade to `0.7.0`. Testing this locally revealed a new vulnerability: ``` $ ./build-support/bin/ci.py --cargo-audit ... Finished release [optimized] target(s) in 6m 11s Replacing /home/jsirois/.cache/pants/rust/cargo/bin/cargo-audit Replaced package `cargo-audit v0.7.0` with `cargo-audit v0.6.1 (https://github.com/RustSec/cargo-audit?rev=1c298bcda2c74f4a1bd8f0d8482b3577ee94fbb3#1c298bcd)` (executable `cargo-audit`) Fetching advisory database from `https://github.com/RustSec/advisory-db.git` Loaded 33 security advisories (from /home/jsirois/.cache/pants/rust/cargo/advisory-db) Scanning src/rust/engine/Cargo.lock for vulnerabilities (334 crate dependencies) error: Vulnerable crates found! ID: RUSTSEC-2019-0011 Crate: memoffset Version: 0.2.1 Date: 2019-07-16 URL: Gilnaa/memoffset#9 (comment) Title: Flaw in offset_of and span_of causes SIGILL, drops uninitialized memory of arbitrary type on panic in client code Solution: upgrade to: >= 0.5.0 error: 1 vulnerability found! Cargo audit failure ``` We don't directly depend on `memoffset`, our root direct dep here is `tokio-threadpool`: ``` $ .cd src/rust/engine && ./../../build-support/bin/native/cargo tree -p memoffset -i memoffset v0.2.1 └── crossbeam-epoch v0.7.1 └── crossbeam-deque v0.7.1 └── tokio-threadpool v0.1.15 ... ├── store v0.1.0 (/home/jsirois/dev/pantsbuild/pants/src/rust/engine/fs/store) ... ``` There is no newer version of `tokio-threadpool`, but a target update solves the issue and gets us to `memoffest` `0.5.11`: ``` $ ./build-support/bin/native/cargo update --manifest-path src/rust/engine/Cargo.toml -p tokio-threadpool --aggressive Updating crates.io index Updating arrayvec v0.4.10 -> v0.4.11 Updating autocfg v0.1.4 -> v0.1.5 Updating crossbeam-epoch v0.7.1 -> v0.7.2 Updating crossbeam-utils v0.6.5 -> v0.6.6 Updating libc v0.2.59 -> v0.2.60 Updating log v0.4.6 -> v0.4.8 Updating memoffset v0.2.1 -> v0.5.1 Updating rand_core v0.4.0 -> v0.4.2 Adding scopeguard v1.0.0 Updating spin v0.5.0 -> v0.5.1 ```
The latest release includes the `--ignore` feature we use, so upgrade to `0.7.0`. Testing this locally revealed a new vulnerability: ``` $ ./build-support/bin/ci.py --cargo-audit ... Finished release [optimized] target(s) in 6m 11s Replacing /home/jsirois/.cache/pants/rust/cargo/bin/cargo-audit Replaced package `cargo-audit v0.7.0` with `cargo-audit v0.6.1 (https://github.com/RustSec/cargo-audit?rev=1c298bcda2c74f4a1bd8f0d8482b3577ee94fbb3#1c298bcd)` (executable `cargo-audit`) Fetching advisory database from `https://github.com/RustSec/advisory-db.git` Loaded 33 security advisories (from /home/jsirois/.cache/pants/rust/cargo/advisory-db) Scanning src/rust/engine/Cargo.lock for vulnerabilities (334 crate dependencies) error: Vulnerable crates found! ID: RUSTSEC-2019-0011 Crate: memoffset Version: 0.2.1 Date: 2019-07-16 URL: Gilnaa/memoffset#9 (comment) Title: Flaw in offset_of and span_of causes SIGILL, drops uninitialized memory of arbitrary type on panic in client code Solution: upgrade to: >= 0.5.0 error: 1 vulnerability found! Cargo audit failure ``` We don't directly depend on `memoffset`, our root direct dep here is `tokio-threadpool`: ``` $ .cd src/rust/engine && ./../../build-support/bin/native/cargo tree -p memoffset -i memoffset v0.2.1 └── crossbeam-epoch v0.7.1 └── crossbeam-deque v0.7.1 └── tokio-threadpool v0.1.15 ... ├── store v0.1.0 (/home/jsirois/dev/pantsbuild/pants/src/rust/engine/fs/store) ... ``` There is no newer version of `tokio-threadpool`, but a target update solves the issue and gets us to `memoffest` `0.5.11`: ``` $ ./build-support/bin/native/cargo update --manifest-path src/rust/engine/Cargo.toml -p tokio-threadpool --aggressive Updating crates.io index Updating arrayvec v0.4.10 -> v0.4.11 Updating autocfg v0.1.4 -> v0.1.5 Updating crossbeam-epoch v0.7.1 -> v0.7.2 Updating crossbeam-utils v0.6.5 -> v0.6.6 Updating libc v0.2.59 -> v0.2.60 Updating log v0.4.6 -> v0.4.8 Updating memoffset v0.2.1 -> v0.5.1 Updating rand_core v0.4.0 -> v0.4.2 Adding scopeguard v1.0.0 Updating spin v0.5.0 -> v0.5.1 ```
The latest release includes the `--ignore` feature we use, so upgrade to `0.7.0`. Testing this locally revealed a new vulnerability: ``` $ ./build-support/bin/ci.py --cargo-audit ... Finished release [optimized] target(s) in 6m 11s Replacing /home/jsirois/.cache/pants/rust/cargo/bin/cargo-audit Replaced package `cargo-audit v0.7.0` with `cargo-audit v0.6.1 (https://github.com/RustSec/cargo-audit?rev=1c298bcda2c74f4a1bd8f0d8482b3577ee94fbb3#1c298bcd)` (executable `cargo-audit`) Fetching advisory database from `https://github.com/RustSec/advisory-db.git` Loaded 33 security advisories (from /home/jsirois/.cache/pants/rust/cargo/advisory-db) Scanning src/rust/engine/Cargo.lock for vulnerabilities (334 crate dependencies) error: Vulnerable crates found! ID: RUSTSEC-2019-0011 Crate: memoffset Version: 0.2.1 Date: 2019-07-16 URL: Gilnaa/memoffset#9 (comment) Title: Flaw in offset_of and span_of causes SIGILL, drops uninitialized memory of arbitrary type on panic in client code Solution: upgrade to: >= 0.5.0 error: 1 vulnerability found! Cargo audit failure ``` We don't directly depend on `memoffset`, our root direct dep here is `tokio-threadpool`: ``` $ .cd src/rust/engine && ./../../build-support/bin/native/cargo tree -p memoffset -i memoffset v0.2.1 └── crossbeam-epoch v0.7.1 └── crossbeam-deque v0.7.1 └── tokio-threadpool v0.1.15 ... ├── store v0.1.0 (/home/jsirois/dev/pantsbuild/pants/src/rust/engine/fs/store) ... ``` There is no newer version of `tokio-threadpool`, but a target update solves the issue and gets us to `memoffest` `0.5.11`: ``` $ ./build-support/bin/native/cargo update --manifest-path src/rust/engine/Cargo.toml -p tokio-threadpool --aggressive Updating crates.io index Updating arrayvec v0.4.10 -> v0.4.11 Updating autocfg v0.1.4 -> v0.1.5 Updating crossbeam-epoch v0.7.1 -> v0.7.2 Updating crossbeam-utils v0.6.5 -> v0.6.6 Updating libc v0.2.59 -> v0.2.60 Updating log v0.4.6 -> v0.4.8 Updating memoffset v0.2.1 -> v0.5.1 Updating rand_core v0.4.0 -> v0.4.2 Adding scopeguard v1.0.0 Updating spin v0.5.0 -> v0.5.1 ```
The latest release includes the `--ignore` feature we use, so upgrade to `0.7.0`. Testing this locally revealed a new vulnerability: ``` $ ./build-support/bin/ci.py --cargo-audit ... Finished release [optimized] target(s) in 6m 11s Replacing /home/jsirois/.cache/pants/rust/cargo/bin/cargo-audit Replaced package `cargo-audit v0.7.0` with `cargo-audit v0.6.1 (https://github.com/RustSec/cargo-audit?rev=1c298bcda2c74f4a1bd8f0d8482b3577ee94fbb3#1c298bcd)` (executable `cargo-audit`) Fetching advisory database from `https://github.com/RustSec/advisory-db.git` Loaded 33 security advisories (from /home/jsirois/.cache/pants/rust/cargo/advisory-db) Scanning src/rust/engine/Cargo.lock for vulnerabilities (334 crate dependencies) error: Vulnerable crates found! ID: RUSTSEC-2019-0011 Crate: memoffset Version: 0.2.1 Date: 2019-07-16 URL: Gilnaa/memoffset#9 (comment) Title: Flaw in offset_of and span_of causes SIGILL, drops uninitialized memory of arbitrary type on panic in client code Solution: upgrade to: >= 0.5.0 error: 1 vulnerability found! Cargo audit failure ``` We don't directly depend on `memoffset`, our root direct dep here is `tokio-threadpool`: ``` $ .cd src/rust/engine && ./../../build-support/bin/native/cargo tree -p memoffset -i memoffset v0.2.1 └── crossbeam-epoch v0.7.1 └── crossbeam-deque v0.7.1 └── tokio-threadpool v0.1.15 ... ├── store v0.1.0 (/home/jsirois/dev/pantsbuild/pants/src/rust/engine/fs/store) ... ``` There is no newer version of `tokio-threadpool`, but a target update solves the issue and gets us to `memoffest` `0.5.11`: ``` $ ./build-support/bin/native/cargo update --manifest-path src/rust/engine/Cargo.toml -p tokio-threadpool --aggressive Updating crates.io index Updating arrayvec v0.4.10 -> v0.4.11 Updating autocfg v0.1.4 -> v0.1.5 Updating crossbeam-epoch v0.7.1 -> v0.7.2 Updating crossbeam-utils v0.6.5 -> v0.6.6 Updating libc v0.2.59 -> v0.2.60 Updating log v0.4.6 -> v0.4.8 Updating memoffset v0.2.1 -> v0.5.1 Updating rand_core v0.4.0 -> v0.4.2 Adding scopeguard v1.0.0 Updating spin v0.5.0 -> v0.5.1 ```
I'll close this issue and open a new one discussing the remaining soundness problems. Most of the discussion here is not relevant any more. |
New issue is at #24. |
With the implementation in:
you are constructing a
&'static T
at address0
. This is undefined behavior because Rust may assume that you have a valid&'static T
but you do not.Moreover, in the old pre-1.33.0 implementation you have:
Note that when you say
&root
you have already triggered undefined behavior because again, you assert with&root
that you have a valid reference but you do not in fact.See rust-lang/rfcs#2582 and rust-lang/unsafe-code-guidelines#77 for a discussion.
As for your comment about
// Future error
, do note thatunsafe { ... }
here does not make what you are doing any less undefined behavior. Instead, while you might not get an error from the compiler, you might get miscompilation should LLVM or rustc's behavior change.cc @RalfJung
The text was updated successfully, but these errors were encountered: