-
Notifications
You must be signed in to change notification settings - Fork 281
Description
See rust-lang/rust#72175 and nix-rust/nix#1421: it seems an external library is allowed to assume a file descriptor is private, for example:
#![allow(clippy::blacklisted_name)]
#![deny(unsafe_code)]
use socket2::SockRef;
use std::mem;
#[allow(unsafe_code)]
mod external_library {
use std::{mem, os::unix::io::RawFd, ptr};
static DATA: i32 = -1;
pub struct Foo([RawFd; 2]);
impl Foo {
pub fn new() -> Self {
let mut sockets = [-1; 2];
assert_eq!(
unsafe {
libc::socketpair(
libc::AF_UNIX,
libc::SOCK_SEQPACKET | libc::SOCK_CLOEXEC,
0,
sockets.as_mut_ptr(),
)
},
0
);
Self(sockets)
}
pub fn foo(&self) {
let data: *const _ = &DATA;
assert_eq!(
unsafe {
libc::send(
self.0[0],
ptr::addr_of!(data).cast(),
mem::size_of_val(&data),
0,
)
},
mem::size_of_val(&data) as _
);
}
pub fn bar(&self) -> i32 {
let mut ptr: *const i32 = ptr::null();
assert_eq!(
unsafe {
libc::recv(
self.0[1],
ptr::addr_of_mut!(ptr).cast(),
mem::size_of_val(&ptr),
0,
)
},
mem::size_of_val(&ptr) as _
);
unsafe { *ptr }
}
}
}
fn main() {
let foo = external_library::Foo::new();
SockRef::from(&3)
.send(&[0; mem::size_of::<*const i32>()])
.unwrap();
foo.foo();
dbg!(foo.bar());
}Here, the safe SockRef::from allows to crash a (fake) "external library" by letting it dereference a null pointer using only safe code. Making functions that accept arbitrary file descriptors or SOCKETs unsafe can probably solve this problem.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels