Skip to content

Commit 77151a7

Browse files
committed
Deprecate unshare and add unshare_unsafe. (#1482)
As pointed out in #1479, `unshare` can lead to threads observing dangling file descriptors. Deprecate it, and add a new `unshare_unsafe` that's unsafe, to reflect this. Fixes #1479.
1 parent 71ecca8 commit 77151a7

File tree

3 files changed

+28
-5
lines changed

3 files changed

+28
-5
lines changed

src/backend/libc/thread/syscalls.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -343,8 +343,8 @@ pub(crate) fn setns(fd: BorrowedFd<'_>, nstype: c::c_int) -> io::Result<c::c_int
343343

344344
#[cfg(linux_kernel)]
345345
#[inline]
346-
pub(crate) fn unshare(flags: crate::thread::UnshareFlags) -> io::Result<()> {
347-
unsafe { ret(c::unshare(flags.bits() as i32)) }
346+
pub(crate) unsafe fn unshare(flags: crate::thread::UnshareFlags) -> io::Result<()> {
347+
ret(c::unshare(flags.bits() as i32))
348348
}
349349

350350
#[cfg(linux_kernel)]

src/backend/linux_raw/thread/syscalls.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -372,8 +372,8 @@ pub(crate) fn setns(fd: BorrowedFd<'_>, nstype: c::c_int) -> io::Result<c::c_int
372372
}
373373

374374
#[inline]
375-
pub(crate) fn unshare(flags: crate::thread::UnshareFlags) -> io::Result<()> {
376-
unsafe { ret(syscall_readonly!(__NR_unshare, flags)) }
375+
pub(crate) unsafe fn unshare(flags: crate::thread::UnshareFlags) -> io::Result<()> {
376+
ret(syscall_readonly!(__NR_unshare, flags))
377377
}
378378

379379
#[inline]

src/thread/setns.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
//! Thread-specific namespace functions.
2+
//!
3+
//! # Safety
4+
//!
5+
//! The `unshare` function can cause threads to use different file descriptor tables.
6+
#![allow(unsafe_code)]
7+
18
use bitflags::bitflags;
29
use linux_raw_sys::general::{
310
CLONE_FILES, CLONE_FS, CLONE_NEWCGROUP, CLONE_NEWIPC, CLONE_NEWNET, CLONE_NEWNS, CLONE_NEWPID,
@@ -127,13 +134,29 @@ pub fn move_into_thread_name_spaces(
127134
syscalls::setns(fd, allowed_types.bits() as c_int).map(|_r| ())
128135
}
129136

137+
/// `unshare(flags)`—Deprecated in favor of [`unshare_unsafe`].
138+
///
139+
/// This function should be unsafe; see the safety comment on `unshare_unsafe`.
140+
#[deprecated(since = "1.1.0", note = "Use `unshare_unsafe`")]
141+
pub fn unshare(flags: UnshareFlags) -> io::Result<()> {
142+
// SAFETY: This is not actually safe. This function is deprecated and users
143+
// should use `unshare_unsafe` instead.
144+
unsafe { syscalls::unshare(flags) }
145+
}
146+
130147
/// `unshare(flags)`—Disassociate parts of the current thread's execution
131148
/// context with other threads.
132149
///
150+
/// # Safety
151+
///
152+
/// When using `UnshareFlags::FILES`, this function can cause one thread to be
153+
/// unable to use file descriptors created on a different thread. Callers must
154+
/// ensure that threads never observe file descriptors from unshared tables.
155+
///
133156
/// # References
134157
/// - [Linux]
135158
///
136159
/// [Linux]: https://man7.org/linux/man-pages/man2/unshare.2.html
137-
pub fn unshare(flags: UnshareFlags) -> io::Result<()> {
160+
pub unsafe fn unshare_unsafe(flags: UnshareFlags) -> io::Result<()> {
138161
syscalls::unshare(flags)
139162
}

0 commit comments

Comments
 (0)