|
#[inline] |
|
pub(in crate::backend) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! { |
|
asm!( |
|
"syscall", |
|
in("rax") nr.to_asm(), |
|
in("rdi") a0.to_asm(), |
|
options(nostack, noreturn) |
|
) |
|
} |
|
#[inline] |
|
pub(crate) fn exit_thread(code: c::c_int) -> ! { |
|
unsafe { syscall_noreturn!(__NR_exit, c_int(code)) } |
|
} |
Every syscall may return
Every syscall may return with any value because of seccomp-bpf.
This includes pure syscalls like getuid that may return the current uid as 4294967295_u32 (-EPERM) or exit/exit_group returning. While such seccomp-bpf filters will have huge compatibility problems and are unlikely in real-world, they must be handled in a safe way.
In the case of exit/exit_group there are two safe possibilities that maintain -> ! to the caller:
- Infinity loop
// Note that this is a pseudo example. If the `sys_exit` function is `-> !`,
// Rust is free to remove the loop because returning from `-> !` is UB.
// The loop must be implemented in assembly with a backward jump
// if the `asm!` is marked `noreturn` as return from the `noreturn`-`asm!`
// is already UB.
loop {
sys_exit(code)
}
- Segfault, i.e.
ud2 (x86-64) after the syscall.
rustix/src/backend/linux_raw/arch/x86_64.rs
Lines 55 to 63 in cb01fbe
rustix/src/backend/linux_raw/runtime/syscalls.rs
Lines 143 to 146 in cb01fbe
Every syscall may return
Every syscall may return with any value because of seccomp-bpf.
This includes pure syscalls like
getuidthat may return the current uid as 4294967295_u32 (-EPERM) orexit/exit_groupreturning. While such seccomp-bpf filters will have huge compatibility problems and are unlikely in real-world, they must be handled in a safe way.In the case of
exit/exit_groupthere are two safe possibilities that maintain-> !to the caller:ud2(x86-64) after thesyscall.