]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
refactor: move sigframe/sigreturn from syscall.c to arch/x86/signal.c
authorTulio A M Mendes <[email protected]>
Fri, 13 Feb 2026 00:33:03 +0000 (21:33 -0300)
committerTulio A M Mendes <[email protected]>
Fri, 13 Feb 2026 02:44:55 +0000 (23:44 -0300)
- 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 [new file with mode: 0644]
include/arch_signal.h [new file with mode: 0644]
src/arch/x86/idt.c
src/arch/x86/signal.c [new file with mode: 0644]
src/kernel/syscall.c

diff --git a/include/arch/x86/signal.h b/include/arch/x86/signal.h
new file mode 100644 (file)
index 0000000..f94e0ac
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef ARCH_X86_SIGNAL_H
+#define ARCH_X86_SIGNAL_H
+
+#include <stdint.h>
+#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 (file)
index 0000000..d68dadd
--- /dev/null
@@ -0,0 +1,19 @@
+#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 */
index c6c3cdfb8367fe68dfbed98d865376db9788a1d2..720699f5d1ce713bd609f458345ec02e0e1e2b1b 100644 (file)
 #include "signal.h"
 #include <stddef.h>
 
-#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 (file)
index 0000000..b70badb
--- /dev/null
@@ -0,0 +1,37 @@
+#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__ */
index 6454f1c3c5fcaa205a83944311267d3df3e6e9f8..a2aa41e1a306efc157f934955aafeaf3546f2d03 100644 (file)
@@ -28,6 +28,7 @@ extern void x86_sysenter_init(void);
 #include "hal/mm.h"
 
 #include "hal/cpu.h"
+#include "arch_signal.h"
 
 #include <stddef.h>
 
@@ -55,14 +56,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);
@@ -1452,30 +1445,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;
@@ -2090,8 +2059,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;
     }