-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Document Rust's stance on /proc/self/mem
#97837
Conversation
Add documentation to `std::os::unix::io` describing Rust's stance on `/proc/self/mem`, treating it as an external entity which is outside the scope of Rust's safety guarantees.
Hey! It looks like you've submitted a new PR for the library teams! If this PR contains changes to any Examples of
|
(rust-highfive has picked a reviewer for you, use r? to override) |
Co-authored-by: Sean Stangl <[email protected]>
Co-authored-by: Sean Stangl <[email protected]>
Co-authored-by: Josh Triplett <[email protected]>
@rfcbot merge |
Team member @joshtriplett has proposed to merge this. The next step is review by the rest of the tagged team members: No concerns currently listed. Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
Co-authored-by: Josh Triplett <[email protected]>
Co-authored-by: Mara Bos <[email protected]>
This adopts the wording suggested in rust-lang#97837 (comment).
🔔 This is now entering its final comment period, as per the review above. 🔔 |
@sunfishcode that seems like a reasonable set of rules. It's a little unclear to me how But is that set of rules what this FCP is approving? Seems unlikely, since it wasn't even written down before now. Maybe it was just unclear to me though. |
Are you asking why we say that resources accessed through the filesystem namespace are safe, when resources accessed through the dynamic linking namespace are unsafe? In the filesystem case, it's because filesystem APIs are widely used, and most of the things that most people do with the filesystem namespace don't cause UB most of the time. Making it unsafe would be coherent, but on a practical level, it would likely do more harm than good. Making it safe is also coherent, using of this internal/external dichotomy, and much more practical, so we do that. In the dynamic linking case, the things the dynamic linker produces are raw pointers. The thing most people do with them most of the time is call them, and if calling them could invoke UB, we have to treat them as unsafe. They're internal in the dichotomy—they're loaded into the program. Encapsulating this unsafety requires knowing the conditions under which they'll invoke UB, and the only way to know that is to know and trust the library they're loaded from, and have a commitment from that library that they'll behave. With that framework in mind:
The proposed change contains a lot fewer words, but I believe it's saying essentially the same thing. Rust isn't alone here; lots of programming languages have effectively the exact same rules, yet as far as I know, none of them document the rules as such. I think there's a widespread assumption that this overall framework is just how computers are understood to work and it doesn't need to be stated. That may mean we have a curse-of-knowledge phenomenon going on. Once one has the intuition here, there seems to be a sense of inevitability about the rules. So perhaps what we're seeing here and in other places where people keep asking questions about this, is that not everyone makes the same assumptions or thinks about this the same way. In that case, perhaps the path forward looks like:
How does that sound? |
This I very much agree with. Rust's stance can be fully justified on pragmatic grounds. What I'm less clear is on is the proposed "internal" and "external" dichotomy. If I understand you right, a hypothetical Also, if Rust could encapsulate "person with a soldering iron" then surely it should do so? The problem with that is a practical one, not a philosophical objection to doing so. |
The underlying mechanism matters. If it's doing
"Is there a boundary?" is philosophical while "where is the boundary?" is practical. |
There is |
In theory, Edit: Also, unlike Edit: It also bypasses /proc/sys/kernel/yama/ptrace_scope even in its most restrictive setting 3, no attach. Edit: I was testing calling |
The final comment period, with a disposition to merge, as per the review above, is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed. This will be merged soon. |
@bors r+ |
📌 Commit 6959441 has been approved by |
I unfortunately didn't get a chance to respond before, and not sure if it's worth doing it now, but I guess I will anyway.
Not at all. There's no other language I know of that attempts to make a formal distinction between "sound" and "unsound," and so no other language has to deal with this issue. I think I've actually made a mistake in not emphasizing this point enough in this conversation. "Sound" and "unsound" are not (supposed to be) vague ideas that represent some philosophical goals, they are concrete concepts that we hope to tie to a formal definition. I don't mean to be rude here, but it frankly seems like this is being hand-waved away both in this conversation and in the PR itself, and I think that is a distinctly dangerous road to go down. I went back and re-read your proposed rules, and honestly I'm not quite sure why I was happy with them the first time around - I don't agree with the distinctions, and I especially don't believe that arguing these kinds of points from a list of examples is a way forward. I have some alternative ideas in mind, and would be happy to discuss more on Zulip instead of here.
Honestly, about as backwards as could be. "Stabilize that this API is sound first and figure out some rules under which that makes sense later" is not at all how these things should work. When we add the language level documentation, what choice will be left for T-Lang and T-types? What if they (like me) don't agree that we can just call this sound? It's not like they'll be able to say no anymore. I suppose it's on me that I failed to ask for this to be nominated for T-Types earlier. I guess it's too late now? |
I mean, it's not set in stone until it reaches stable? I think you can still discuss this on Zulip and ask t-libs if you have reasons they might want to reconsider. I personally don't want to take issue with |
Yeah, agreed. If this was just documenting that std doesn't care about protecting you from That's a good point about us having until this reaches stable. I might bring this up with T-types on zulip then (as they are the proper team to be making this decision). Later though, it is bed time for me right now |
Rollup of 8 pull requests Successful merges: - rust-lang#93080 (Implement `core::slice::IterMut::as_mut_slice` and `impl<T> AsMut<[T]> for IterMut<'_, T>`) - rust-lang#94855 (Panic when advance_slices()'ing too far and update docs.) - rust-lang#96609 (Add `{Arc, Rc}::downcast_unchecked`) - rust-lang#96719 (Fix the generator example for `pin!()`) - rust-lang#97149 (Windows: `CommandExt::async_pipes`) - rust-lang#97150 (`Stdio::makes_pipe`) - rust-lang#97837 (Document Rust's stance on `/proc/self/mem`) - rust-lang#98159 (Include ForeignItem when visiting types for WF check) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
For anyone else looking, this doc-comment ends up visible at: https://doc.rust-lang.org/nightly/std/os/unix/io/index.html#procselfmem-and-similar-os-features |
This adopts the wording suggested in rust-lang/rust#97837 (comment).
Pkgsrc changes: * Adjust patches as needed & checksum updates. Upstream changes: Version 1.63.0 (2022-08-11) ========================== Language -------- - [Remove migrate borrowck mode for pre-NLL errors.][95565] - [Modify MIR building to drop repeat expressions with length zero.][95953] - [Remove label/lifetime shadowing warnings.][96296] - [Allow explicit generic arguments in the presence of `impl Trait` args.] [96868] - [Make `cenum_impl_drop_cast` warnings deny-by-default.][97652] - [Prevent unwinding when `-C panic=abort` is used regardless of declared ABI.][96959] - [lub: don't bail out due to empty binders.][97867] Compiler -------- - [Stabilize the `bundle` native library modifier,][95818] also removing the deprecated `static-nobundle` linking kind. - [Add Apple WatchOS compile targets\*.][95243] - [Add a Windows application manifest to rustc-main.][96737] \* Refer to Rust's [platform support page][platform-support-doc] for more information on Rust's tiered platform support. Libraries --------- - [Implement `Copy`, `Clone`, `PartialEq` and `Eq` for `core::fmt::Alignment`.][94530] - [Extend `ptr::null` and `null_mut` to all thin (including extern) types.][94954] - [`impl Read and Write for VecDeque<u8>`.][95632] - [STD support for the Nintendo 3DS.][95897] - [Make write/print macros eagerly drop temporaries.][96455] - [Implement internal traits that enable `[OsStr]::join`.][96881] - [Implement `Hash` for `core::alloc::Layout`.][97034] - [Add capacity documentation for `OsString`.][97202] - [Put a bound on collection misbehavior.][97316] - [Make `std::mem::needs_drop` accept `?Sized`.][97675] - [`impl Termination for Infallible` and then make the `Result` impls of `Termination` more generic.][97803] - [Document Rust's stance on `/proc/self/mem`.][97837] Stabilized APIs --------------- - [`array::from_fn`] - [`Box::into_pin`] - [`BinaryHeap::try_reserve`] - [`BinaryHeap::try_reserve_exact`] - [`OsString::try_reserve`] - [`OsString::try_reserve_exact`] - [`PathBuf::try_reserve`] - [`PathBuf::try_reserve_exact`] - [`Path::try_exists`] - [`Ref::filter_map`] - [`RefMut::filter_map`] - [`NonNull::<[T]>::len`][`NonNull::<slice>::len`] - [`ToOwned::clone_into`] - [`Ipv6Addr::to_ipv4_mapped`] - [`unix::io::AsFd`] - [`unix::io::BorrowedFd<'fd>`] - [`unix::io::OwnedFd`] - [`windows::io::AsHandle`] - [`windows::io::BorrowedHandle<'handle>`] - [`windows::io::OwnedHandle`] - [`windows::io::HandleOrInvalid`] - [`windows::io::HandleOrNull`] - [`windows::io::InvalidHandleError`] - [`windows::io::NullHandleError`] - [`windows::io::AsSocket`] - [`windows::io::BorrowedSocket<'handle>`] - [`windows::io::OwnedSocket`] - [`thread::scope`] - [`thread::Scope`] - [`thread::ScopedJoinHandle`] These APIs are now usable in const contexts: - [`array::from_ref`] - [`slice::from_ref`] - [`intrinsics::copy`] - [`intrinsics::copy_nonoverlapping`] - [`<*const T>::copy_to`] - [`<*const T>::copy_to_nonoverlapping`] - [`<*mut T>::copy_to`] - [`<*mut T>::copy_to_nonoverlapping`] - [`<*mut T>::copy_from`] - [`<*mut T>::copy_from_nonoverlapping`] - [`str::from_utf8`] - [`Utf8Error::error_len`] - [`Utf8Error::valid_up_to`] - [`Condvar::new`] - [`Mutex::new`] - [`RwLock::new`] Cargo ----- - [Stabilize the `--config path` command-line argument.][cargo/10755] - [Expose rust-version in the environment as `CARGO_PKG_RUST_VERSION`.][cargo/10713] Compatibility Notes ------------------- - [`#[link]` attributes are now checked more strictly,][96885] which may introduce errors for invalid attribute arguments that were previously ignored. Internal Changes ---------------- These changes provide no direct user facing benefits, but represent significant improvements to the internals and overall performance of rustc and related tools. - [Prepare Rust for LLVM opaque pointers.][94214] [94214]: rust-lang/rust#94214 [94530]: rust-lang/rust#94530 [94954]: rust-lang/rust#94954 [95243]: rust-lang/rust#95243 [95565]: rust-lang/rust#95565 [95632]: rust-lang/rust#95632 [95818]: rust-lang/rust#95818 [95897]: rust-lang/rust#95897 [95953]: rust-lang/rust#95953 [96296]: rust-lang/rust#96296 [96455]: rust-lang/rust#96455 [96737]: rust-lang/rust#96737 [96868]: rust-lang/rust#96868 [96881]: rust-lang/rust#96881 [96885]: rust-lang/rust#96885 [96959]: rust-lang/rust#96959 [97034]: rust-lang/rust#97034 [97202]: rust-lang/rust#97202 [97316]: rust-lang/rust#97316 [97652]: rust-lang/rust#97652 [97675]: rust-lang/rust#97675 [97803]: rust-lang/rust#97803 [97837]: rust-lang/rust#97837 [97867]: rust-lang/rust#97867 [cargo/10713]: rust-lang/cargo#10713 [cargo/10755]: rust-lang/cargo#10755 [`array::from_fn`]: https://doc.rust-lang.org/stable/std/array/fn.from_fn.html [`Box::into_pin`]: https://doc.rust-lang.org/stable/std/boxed/struct.Box.html#method.into_pin [`BinaryHeap::try_reserve_exact`]: https://doc.rust-lang.org/stable/alloc/collections/binary_heap/struct.BinaryHeap.html#method.try_reserve_exact [`BinaryHeap::try_reserve`]: https://doc.rust-lang.org/stable/std/collections/struct.BinaryHeap.html#method.try_reserve [`OsString::try_reserve`]: https://doc.rust-lang.org/stable/std/ffi/struct.OsString.html#method.try_reserve [`OsString::try_reserve_exact`]: https://doc.rust-lang.org/stable/std/ffi/struct.OsString.html#method.try_reserve_exact [`PathBuf::try_reserve`]: https://doc.rust-lang.org/stable/std/path/struct.PathBuf.html#method.try_reserve [`PathBuf::try_reserve_exact`]: https://doc.rust-lang.org/stable/std/path/struct.PathBuf.html#method.try_reserve_exact [`Path::try_exists`]: https://doc.rust-lang.org/stable/std/path/struct.Path.html#method.try_exists [`Ref::filter_map`]: https://doc.rust-lang.org/stable/std/cell/struct.Ref.html#method.filter_map [`RefMut::filter_map`]: https://doc.rust-lang.org/stable/std/cell/struct.RefMut.html#method.filter_map [`NonNull::<slice>::len`]: https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html#method.len [`ToOwned::clone_into`]: https://doc.rust-lang.org/stable/std/borrow/trait.ToOwned.html#method.clone_into [`Ipv6Addr::to_ipv4_mapped`]: https://doc.rust-lang.org/stable/std/net/struct.Ipv6Addr.html#method.to_ipv4_mapped [`unix::io::AsFd`]: https://doc.rust-lang.org/stable/std/os/unix/io/trait.AsFd.html [`unix::io::BorrowedFd<'fd>`]: https://doc.rust-lang.org/stable/std/os/unix/io/struct.BorrowedFd.html [`unix::io::OwnedFd`]: https://doc.rust-lang.org/stable/std/os/unix/io/struct.OwnedFd.html [`windows::io::AsHandle`]: https://doc.rust-lang.org/stable/std/os/windows/io/trait.AsHandle.html [`windows::io::BorrowedHandle<'handle>`]: https://doc.rust-lang.org/stable/std/os/windows/io/struct.BorrowedHandle.html [`windows::io::OwnedHandle`]: https://doc.rust-lang.org/stable/std/os/windows/io/struct.OwnedHandle.html [`windows::io::HandleOrInvalid`]: https://doc.rust-lang.org/stable/std/os/windows/io/struct.HandleOrInvalid.html [`windows::io::HandleOrNull`]: https://doc.rust-lang.org/stable/std/os/windows/io/struct.HandleOrNull.html [`windows::io::InvalidHandleError`]: https://doc.rust-lang.org/stable/std/os/windows/io/struct.InvalidHandleError.html [`windows::io::NullHandleError`]: https://doc.rust-lang.org/stable/std/os/windows/io/struct.NullHandleError.html [`windows::io::AsSocket`]: https://doc.rust-lang.org/stable/std/os/windows/io/trait.AsSocket.html [`windows::io::BorrowedSocket<'handle>`]: https://doc.rust-lang.org/stable/std/os/windows/io/struct.BorrowedSocket.html [`windows::io::OwnedSocket`]: https://doc.rust-lang.org/stable/std/os/windows/io/struct.OwnedSocket.html [`thread::scope`]: https://doc.rust-lang.org/stable/std/thread/fn.scope.html [`thread::Scope`]: https://doc.rust-lang.org/stable/std/thread/struct.Scope.html [`thread::ScopedJoinHandle`]: https://doc.rust-lang.org/stable/std/thread/struct.ScopedJoinHandle.html [`array::from_ref`]: https://doc.rust-lang.org/stable/std/array/fn.from_ref.html [`slice::from_ref`]: https://doc.rust-lang.org/stable/std/slice/fn.from_ref.html [`intrinsics::copy`]: https://doc.rust-lang.org/stable/std/intrinsics/fn.copy.html [`intrinsics::copy_nonoverlapping`]: https://doc.rust-lang.org/stable/std/intrinsics/fn.copy_nonoverlapping.html [`<*const T>::copy_to`]: https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.copy_to [`<*const T>::copy_to_nonoverlapping`]: https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.copy_to_nonoverlapping [`<*mut T>::copy_to`]: https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.copy_to-1 [`<*mut T>::copy_to_nonoverlapping`]: https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.copy_to_nonoverlapping-1 [`<*mut T>::copy_from`]: https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.copy_from [`<*mut T>::copy_from_nonoverlapping`]: https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.copy_from_nonoverlapping [`str::from_utf8`]: https://doc.rust-lang.org/stable/std/str/fn.from_utf8.html [`Utf8Error::error_len`]: https://doc.rust-lang.org/stable/std/str/struct.Utf8Error.html#method.error_len [`Utf8Error::valid_up_to`]: https://doc.rust-lang.org/stable/std/str/struct.Utf8Error.html#method.valid_up_to [`Condvar::new`]: https://doc.rust-lang.org/stable/std/sync/struct.Condvar.html#method.new [`Mutex::new`]: https://doc.rust-lang.org/stable/std/sync/struct.Mutex.html#method.new [`RwLock::new`]: https://doc.rust-lang.org/stable/std/sync/struct.RwLock.html#method.new
Add documentation to
std::os::unix::io
describing Rust's stance on/proc/self/mem
, treating it as an external entity which is outsidethe scope of Rust's safety guarantees.