Skip to content

Commit fa4a9d6

Browse files
committed
Fail explicitly for unsupported clone flags on MIPS
O32 ABI requires child_tid (5th arg) on stack, which we don't do. Check for CLONE_CHILD_CLEARTID/SETTID upfront and return EOPNOTSUPP.
1 parent b542a14 commit fa4a9d6

File tree

1 file changed

+18
-9
lines changed

1 file changed

+18
-9
lines changed

src/arch/mips32.rs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ use linux_raw_sys::general::{__NR_mprotect, PROT_READ};
1515
#[cfg(feature = "thread")]
1616
use {
1717
core::ffi::c_void,
18-
linux_raw_sys::general::{__NR_clone, __NR_exit, __NR_munmap, __NR_set_thread_area},
18+
linux_raw_sys::general::{
19+
__NR_clone, __NR_exit, __NR_munmap, __NR_set_thread_area, CLONE_CHILD_CLEARTID,
20+
CLONE_CHILD_SETTID,
21+
},
1922
rustix::thread::RawPid,
2023
};
2124

@@ -256,23 +259,32 @@ pub(super) unsafe fn relocation_mprotect_readonly(ptr: usize, len: usize) {
256259
#[cfg(feature = "thread")]
257260
pub(super) const STACK_ALIGNMENT: usize = 8;
258261

259-
/// A wrapper around the Linux `clone` system call.
262+
// MIPS errno value for "operation not supported" (different from x86's 95).
263+
#[cfg(feature = "take-charge")]
264+
#[cfg(feature = "thread")]
265+
const EOPNOTSUPP: i32 = 122;
266+
267+
/// Linux `clone` syscall wrapper. Inline asm required because child resumes
268+
/// at same point as parent and must jump to our thread entrypoint.
260269
///
261-
/// This can't be implemented in `rustix` because the child starts executing at
262-
/// the same point as the parent and we need to use inline asm to have the
263-
/// child jump to our new-thread entrypoint.
270+
/// CLONE_CHILD_CLEARTID/SETTID unsupported (O32 ABI needs child_tid on stack).
264271
#[cfg(feature = "take-charge")]
265272
#[cfg(feature = "thread")]
266273
#[inline]
267274
pub(super) unsafe fn clone(
268275
flags: u32,
269276
child_stack: *mut c_void,
270277
parent_tid: *mut RawPid,
271-
child_tid: *mut RawPid,
278+
_child_tid: *mut RawPid, // unused: O32 ABI needs stack passing, not implemented
272279
newtls: *mut c_void,
273280
fn_: extern "C" fn(),
274281
num_args: usize,
275282
) -> isize {
283+
// Fail explicitly for flags that require child_tid, which we don't pass.
284+
if flags & (CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID) != 0 {
285+
return -(EOPNOTSUPP as isize);
286+
}
287+
276288
unsafe {
277289
let r0;
278290
asm!(
@@ -318,9 +330,6 @@ pub(super) unsafe fn clone(
318330
lateout("$t9") _,
319331
options(nostack)
320332
);
321-
// Note: child_tid handling is simplified here; full implementation would
322-
// need to push it to the stack frame per O32 calling convention.
323-
let _ = child_tid;
324333
r0
325334
}
326335
}

0 commit comments

Comments
 (0)