Skip to content

Commit 56e1277

Browse files
djkoloskiasomers
andauthored
Make clone unsafe (#1993)
* Make `clone` unsafe There are many features of `clone` that may cause memory unsafety when called. This documents one of them and references `fork()`, which is already unsafe to call. * Adjust the clone entry in the CHANGELOG --------- Co-authored-by: Alan Somers <asomers@gmail.com>
1 parent 93d43a7 commit 56e1277

File tree

2 files changed

+25
-15
lines changed

2 files changed

+25
-15
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ This project adheres to [Semantic Versioning](https://semver.org/).
6969
See ([#2097](https://github.com/nix-rust/nix/pull/2097))
7070
- Refactored `name` parameter of `mq_open` and `mq_unlink` to be generic over
7171
`NixPath`. See ([#2102](https://github.com/nix-rust/nix/pull/2102)).
72+
- Made `clone` unsafe, like `fork`.
73+
([#1993](https://github.com/nix-rust/nix/pull/1993))
7274

7375
### Fixed
7476
- Fix: send `ETH_P_ALL` in htons format

src/sched.rs

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,17 @@ mod sched_linux_like {
9595
/// address need not be the highest address of the region. Nix will take
9696
/// care of that requirement. The user only needs to provide a reference to
9797
/// a normally allocated buffer.
98-
pub fn clone(
98+
///
99+
/// # Safety
100+
///
101+
/// Because `clone` creates a child process with its stack located in
102+
/// `stack` without specifying the size of the stack, special care must be
103+
/// taken to ensure that the child process does not overflow the provided
104+
/// stack space.
105+
///
106+
/// See [`fork`](crate::unistd::fork) for additional safety concerns related
107+
/// to executing child processes.
108+
pub unsafe fn clone(
99109
mut cb: CloneCb,
100110
stack: &mut [u8],
101111
flags: CloneFlags,
@@ -106,20 +116,18 @@ mod sched_linux_like {
106116
(*cb)() as c_int
107117
}
108118

109-
let res = unsafe {
110-
let combined = flags.bits() | signal.unwrap_or(0);
111-
let ptr = stack.as_mut_ptr().add(stack.len());
112-
let ptr_aligned = ptr.sub(ptr as usize % 16);
113-
libc::clone(
114-
mem::transmute(
115-
callback
116-
as extern "C" fn(*mut Box<dyn FnMut() -> isize>) -> i32,
117-
),
118-
ptr_aligned as *mut c_void,
119-
combined,
120-
&mut cb as *mut _ as *mut c_void,
121-
)
122-
};
119+
let combined = flags.bits() | signal.unwrap_or(0);
120+
let ptr = stack.as_mut_ptr().add(stack.len());
121+
let ptr_aligned = ptr.sub(ptr as usize % 16);
122+
let res = libc::clone(
123+
mem::transmute(
124+
callback
125+
as extern "C" fn(*mut Box<dyn FnMut() -> isize>) -> i32,
126+
),
127+
ptr_aligned as *mut c_void,
128+
combined,
129+
&mut cb as *mut _ as *mut c_void,
130+
);
123131

124132
Errno::result(res).map(Pid::from_raw)
125133
}

0 commit comments

Comments
 (0)