Skip to content

Commit 35866b9

Browse files
authored
Fix sigreturn for x86 (#668)
According to [Linux](https://elixir.bootlin.com/linux/v5.19.17/source/arch/x86/kernel/signal.c#L633), `esp - 8` should point to `SignalFrame` instead of `LegacyContext`. We could also remove the ` - 8` and following `wrapping_add` directly but keep it just to be consistent with Linux. There are some potential overflow issues where we perform some arithmetic operations on user provided input. We should always use `checked_*` or `wrapping_*`. There are likely more similar issues in the codebase, and this PR only fixes the ones related to `sigreturn`.
1 parent 4cef3fa commit 35866b9

File tree

2 files changed

+8
-7
lines changed

2 files changed

+8
-7
lines changed

litebox_shim_linux/src/syscalls/signal/x86.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ struct SignalFrameRt {
4242
impl<FS: crate::ShimFS> Task<FS> {
4343
/// Legacy signal return syscall implementation for x86.
4444
pub(crate) fn sys_sigreturn(&self, ctx: &mut PtRegs) -> Result<usize, Errno> {
45-
let lctx_addr = ctx.esp.wrapping_sub(8);
45+
let sigframe_addr = ctx.esp.wrapping_sub(8);
46+
let lctx_addr = sigframe_addr.wrapping_add(offset_of!(SignalFrame, context));
4647
let lctx_ptr = ConstPtr::<LegacyContext>::from_usize(lctx_addr);
4748
let Some(lctx) = lctx_ptr.read_at_offset(0) else {
4849
self.force_signal(Signal::SIGSEGV, false);
@@ -73,14 +74,14 @@ pub(super) fn get_signal_frame(sp: usize, action: &SigAction) -> usize {
7374

7475
// Space for the signal frame.
7576
if action.flags.contains(SaFlags::SIGINFO) {
76-
frame_addr -= core::mem::size_of::<SignalFrameRt>();
77+
frame_addr = frame_addr.wrapping_sub(core::mem::size_of::<SignalFrameRt>());
7778
} else {
78-
frame_addr -= core::mem::size_of::<SignalFrame>();
79+
frame_addr = frame_addr.wrapping_sub(core::mem::size_of::<SignalFrame>());
7980
}
8081

8182
// Align the frame (offset by 4 bytes for return address).
8283
frame_addr &= !15;
83-
frame_addr -= 4;
84+
frame_addr = frame_addr.wrapping_sub(4);
8485

8586
frame_addr
8687
}

litebox_shim_linux/src/syscalls/signal/x86_64.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,14 @@ pub(super) fn get_signal_frame(sp: usize, _action: &SigAction) -> usize {
3232
let mut frame_addr = sp;
3333

3434
// Skip the redzone.
35-
frame_addr -= 128;
35+
frame_addr = frame_addr.wrapping_sub(128);
3636

3737
// Space for the signal frame.
38-
frame_addr -= core::mem::size_of::<SignalFrame>();
38+
frame_addr = frame_addr.wrapping_sub(core::mem::size_of::<SignalFrame>());
3939

4040
// Align the frame (offset by 8 bytes for return address)
4141
frame_addr &= !15;
42-
frame_addr -= 8;
42+
frame_addr = frame_addr.wrapping_sub(8);
4343

4444
frame_addr
4545
}

0 commit comments

Comments
 (0)