]> 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..d564cd4
--- /dev/null
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2018, Tulio A M Mendes <[email protected]>
+ * All rights reserved.
+ * See LICENSE for details.
+ *
+ * Source: https://github.com/tadryanom/AdrOS
+ */
+
+#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..436fc57
--- /dev/null
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2018, Tulio A M Mendes <[email protected]>
+ * 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 */
index 2b73be8f295deb6805ff5f24bc23c870be94aaf6..e0971e15597ee6a3d8e9b4c2bc41bb46b612fed6 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..89705e1
--- /dev/null
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2018, Tulio A M Mendes <[email protected]>
+ * 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__ */
index 056115e5eab34249487337f283c5785b3fa3b0cf..10511f0e28998c2ea88291c3e1c6b5912d281e92 100644 (file)
@@ -37,6 +37,7 @@ extern void x86_sysenter_init(void);
 #include "hal/mm.h"
 
 #include "hal/cpu.h"
+#include "arch_signal.h"
 
 #include <stddef.h>
 
@@ -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;
     }