--- /dev/null
+#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 */
--- /dev/null
+#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 */
#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;
--- /dev/null
+#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__ */
#include "hal/mm.h"
#include "hal/cpu.h"
+#include "arch_signal.h"
#include <stddef.h>
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);
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;
}
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;
}