From 54542cc46a070718d6c509c5fe224961a0a81000 Mon Sep 17 00:00:00 2001 From: Tulio A M Mendes Date: Thu, 12 Feb 2026 21:33:03 -0300 Subject: [PATCH] refactor: move sigframe/sigreturn from syscall.c to arch/x86/signal.c - New include/arch/x86/signal.h: shared struct sigframe + SIGFRAME_MAGIC - New include/arch_signal.h: arch-agnostic arch_sigreturn() prototype - New src/arch/x86/signal.c: x86 sigreturn implementation (eflags sanitize, CS/SS ring3 validation, IOPL clear) - src/arch/x86/idt.c: use shared arch/x86/signal.h instead of local copy - src/kernel/syscall.c: remove x86-specific sigframe struct and sigreturn_impl, call arch_sigreturn() via generic void* interface No x86 signal frame knowledge remains in generic kernel code. --- include/arch/x86/signal.h | 23 ++++++++++++++++++++ include/arch_signal.h | 28 ++++++++++++++++++++++++ src/arch/x86/idt.c | 9 ++------ src/arch/x86/signal.c | 46 +++++++++++++++++++++++++++++++++++++++ src/kernel/syscall.c | 37 +++---------------------------- 5 files changed, 102 insertions(+), 41 deletions(-) create mode 100644 include/arch/x86/signal.h create mode 100644 include/arch_signal.h create mode 100644 src/arch/x86/signal.c diff --git a/include/arch/x86/signal.h b/include/arch/x86/signal.h new file mode 100644 index 00000000..d564cd48 --- /dev/null +++ b/include/arch/x86/signal.h @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2018, Tulio A M Mendes + * All rights reserved. + * See LICENSE for details. + * + * Source: https://github.com/tadryanom/AdrOS + */ + +#ifndef ARCH_X86_SIGNAL_H +#define ARCH_X86_SIGNAL_H + +#include +#include "arch/x86/idt.h" + +#define SIGFRAME_MAGIC 0x53494746U /* 'SIGF' */ + +struct sigframe { + uint32_t magic; + struct registers saved; +}; + +#endif /* ARCH_X86_SIGNAL_H */ diff --git a/include/arch_signal.h b/include/arch_signal.h new file mode 100644 index 00000000..436fc573 --- /dev/null +++ b/include/arch_signal.h @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2018, Tulio A M Mendes + * All rights reserved. + * See LICENSE for details. + * + * Source: https://github.com/tadryanom/AdrOS + */ + +#ifndef ARCH_SIGNAL_H +#define ARCH_SIGNAL_H + +#include "interrupts.h" + +/* + * arch_sigreturn — Restore user registers from a signal frame on the + * user stack. Architecture-specific because the frame + * layout and register sanitisation depend on the ISA. + * + * regs : current trapframe (will be overwritten on success). + * user_frame : user-space pointer to the signal frame pushed by the + * signal delivery trampoline. + * + * Returns 0 on success, negative errno on failure. + */ +int arch_sigreturn(struct registers* regs, const void* user_frame); + +#endif /* ARCH_SIGNAL_H */ diff --git a/src/arch/x86/idt.c b/src/arch/x86/idt.c index 2b73be8f..e0971e15 100644 --- a/src/arch/x86/idt.c +++ b/src/arch/x86/idt.c @@ -19,14 +19,9 @@ #include "signal.h" #include -#define IDT_ENTRIES 256 - -static const uint32_t SIGFRAME_MAGIC = 0x53494746U; // 'SIGF' +#include "arch/x86/signal.h" -struct sigframe { - uint32_t magic; - struct registers saved; -}; +#define IDT_ENTRIES 256 struct idt_entry idt[IDT_ENTRIES]; struct idt_ptr idtp; diff --git a/src/arch/x86/signal.c b/src/arch/x86/signal.c new file mode 100644 index 00000000..89705e1b --- /dev/null +++ b/src/arch/x86/signal.c @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2018, Tulio A M Mendes + * All rights reserved. + * See LICENSE for details. + * + * Source: https://github.com/tadryanom/AdrOS + */ + +#include "arch_signal.h" +#include "arch/x86/signal.h" +#include "process.h" +#include "uaccess.h" +#include "errno.h" + +#if defined(__i386__) + +int arch_sigreturn(struct registers* regs, const void* user_frame) +{ + if (!regs) return -EINVAL; + if (!current_process) return -EINVAL; + if ((regs->cs & 3U) != 3U) return -EPERM; + if (!user_frame) return -EFAULT; + + if (user_range_ok(user_frame, sizeof(struct sigframe)) == 0) + return -EFAULT; + + struct sigframe f; + if (copy_from_user(&f, user_frame, sizeof(f)) < 0) + return -EFAULT; + if (f.magic != SIGFRAME_MAGIC) + return -EINVAL; + + if ((f.saved.cs & 3U) != 3U) return -EPERM; + if ((f.saved.ss & 3U) != 3U) return -EPERM; + + // Sanitize eflags: clear IOPL (bits 12-13) to prevent privilege escalation, + // ensure IF (bit 9) is set so interrupts remain enabled in usermode. + f.saved.eflags = (f.saved.eflags & ~0x3000U) | 0x200U; + + // Restore the full saved trapframe. The interrupt stub will pop these regs and iret. + *regs = f.saved; + return 0; +} + +#endif /* __i386__ */ diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c index 056115e5..10511f0e 100644 --- a/src/kernel/syscall.c +++ b/src/kernel/syscall.c @@ -37,6 +37,7 @@ extern void x86_sysenter_init(void); #include "hal/mm.h" #include "hal/cpu.h" +#include "arch_signal.h" #include @@ -64,14 +65,6 @@ enum { static int path_resolve_user(const char* user_path, char* out, size_t out_sz); -#if defined(__i386__) -static const uint32_t SIGFRAME_MAGIC = 0x53494746U; // 'SIGF' -struct sigframe { - uint32_t magic; - struct registers saved; -}; -#endif - static int fd_alloc(struct file* f); static int fd_close(int fd); static struct file* fd_get(int fd); @@ -1461,30 +1454,6 @@ static int syscall_sigprocmask_impl(uint32_t how, uint32_t mask, uint32_t* old_o return -EINVAL; } -static int syscall_sigreturn_impl(struct registers* regs, const struct sigframe* user_frame) { - if (!regs) return -EINVAL; - if (!current_process) return -EINVAL; - if ((regs->cs & 3U) != 3U) return -EPERM; - if (!user_frame) return -EFAULT; - - if (user_range_ok(user_frame, sizeof(*user_frame)) == 0) { return -EFAULT; } - - struct sigframe f; - if (copy_from_user(&f, user_frame, sizeof(f)) < 0) return -EFAULT; - if (f.magic != SIGFRAME_MAGIC) { return -EINVAL; } - - if ((f.saved.cs & 3U) != 3U) return -EPERM; - if ((f.saved.ss & 3U) != 3U) return -EPERM; - - // Sanitize eflags: clear IOPL (bits 12-13) to prevent privilege escalation, - // ensure IF (bit 9) is set so interrupts remain enabled in usermode. - f.saved.eflags = (f.saved.eflags & ~0x3000U) | 0x200U; - - // Restore the full saved trapframe. The interrupt stub will pop these regs and iret. - *regs = f.saved; - return 0; -} - struct timespec { uint32_t tv_sec; uint32_t tv_nsec; @@ -2099,8 +2068,8 @@ void syscall_handler(struct registers* regs) { } if (syscall_no == SYSCALL_SIGRETURN) { - const struct sigframe* user_frame = (const struct sigframe*)regs->ebx; - regs->eax = (uint32_t)syscall_sigreturn_impl(regs, user_frame); + const void* user_frame = (const void*)(uintptr_t)regs->ebx; + regs->eax = (uint32_t)arch_sigreturn(regs, user_frame); return; } -- 2.43.0