profile
viewpoint

Ask questionsDocument FromRawFd unsafety

Currently the documentation of FromRawFd uses vague language:

This function is also unsafe as the primitives currently returned have the contract that they are the sole owner of the file descriptor they are wrapping. Usage of this function could accidentally allow violating this contract which can cause memory unsafety in code that relies on it being true.

What kind of memory safety issues is this quote referring to?

Using the nix crate it is not hard to write FromRawFd using only safe code:

use nix::{
    fcntl::{open, OFlag},
    sys::stat::Mode,
    unistd::dup2,
};
use std::{
    fs::{self, File},
    io::Read,
    os::unix::io::AsRawFd,
};

fn main() {
    fs::write("a", "a").unwrap();
    fs::write("b", "b").unwrap();

    let mut a = File::open("a").unwrap();
    let b = open("b", OFlag::O_RDONLY, Mode::empty()).unwrap();

    dup2(b, a.as_raw_fd()).unwrap();

    let mut a_contents = String::new();
    a.read_to_string(&mut a_contents).unwrap();

    assert!(a_contents == "b");
}

This is the simplest way but you can also use close on the returned file descriptor and then call File::open again to create two Files with the same underlying file descriptor.

What about performing the various fcntl operation on the value returned by as_raw_fd? Can these also cause memory unsafety? Must all methods operating on file descriptors in nix be marked unsafe because as_raw_fd is a safe function?

Given the current state of the AsRawFd and the existence of other safe crates which allow manipulating the returned file descriptor, there should be very good reasons to keep from_raw_fd unsafe and these should be documented. Otherwise from_raw_fd should be made safe with a clear warning that odd (but not unsafe) things might happen if the assumptions about ownership are violated.

rust-lang/rust

Answer questions mahkoh

It's actually more ridiculous than that. The referenced issue https://github.com/rust-lang/rfcs/issues/1043 contains an elementary mistake:

fn main() {
    let f = File::create(...);
    let f2 = File::from_raw_fd(f.as_raw_fd());
    let m = MemoryMap::new(f).unwrap();
    drop(f2);
    // Use m and segfault...
}

Since mmap performs the equivalent of dup, there would not have been a segfault in the first place. Furthermore, the use of file-backed mmap can never be safe because the file (and thus the mapped memory) can be changed by other processed at will.

useful!

Related questions

Spurious NaNs produced by trig functions with valid inputs on Windows GNU toolchains hot 3
Archive all nightlies hot 3
using 'cargo install xsv' on windows 10 triggers rustc internal error hot 2
if/while Some(n) = &mut foo sugar will leak a temporary mutable borrow to current scope in particular situation hot 2
under latest MinGW, cannot link with C code using stdout hot 2
chain() make collect very slow hot 1
build an empty project failed (undefined reference to `__onexitbegin') hot 1
Invalid collision with TryFrom implementation? hot 1
Crater runs for Rust 1.38.0 hot 1
Spurious NaNs produced by trig functions with valid inputs on Windows GNU toolchains hot 1
Building LLVM with Clang fails hot 1
Internal compiler error: can't buffer lints after HIR lowering hot 1
E0373 help suggests `move async` but the correct syntax is `async move` hot 1
Tracking issue for `Option::contains` and `Result::contains` hot 1
async fn + rustfmt don't "just work" inside of RLS hot 1
source:https://uonfu.com/
Github User Rank List