struct sigaction sigactions[PROCESS_MAX_SIG];
uint32_t sig_blocked_mask;
uint32_t sig_pending_mask;
+ uintptr_t ss_sp; /* alternate signal stack pointer */
+ uint32_t ss_size; /* alternate signal stack size */
+ uint32_t ss_flags; /* SS_DISABLE etc. */
// For SIGSEGV: last page fault address (CR2) captured in ring3.
uintptr_t last_fault_addr;
return;
}
- if (syscall_no == SYSCALL_TIMES || syscall_no == SYSCALL_FUTEX) {
+ if (syscall_no == SYSCALL_SIGALTSTACK ||
+ syscall_no == SYSCALL_TIMES || syscall_no == SYSCALL_FUTEX) {
posix_ext_syscall_dispatch(regs, syscall_no);
return;
}
return;
}
+ if (syscall_no == SYSCALL_SIGALTSTACK) {
+ if (!current_process) { regs->eax = (uint32_t)-EINVAL; return; }
+ #ifndef SS_DISABLE
+ #define SS_DISABLE 2
+ #endif
+ uint32_t* user_old = (uint32_t*)regs->ecx;
+ uint32_t* user_new = (uint32_t*)regs->ebx;
+ if (user_old) {
+ uint32_t old_ss[3];
+ old_ss[0] = (uint32_t)current_process->ss_sp;
+ old_ss[1] = current_process->ss_flags;
+ old_ss[2] = current_process->ss_size;
+ if (copy_to_user(user_old, old_ss, 12) < 0) {
+ regs->eax = (uint32_t)-EFAULT; return;
+ }
+ }
+ if (user_new) {
+ uint32_t new_ss[3];
+ if (copy_from_user(new_ss, user_new, 12) < 0) {
+ regs->eax = (uint32_t)-EFAULT; return;
+ }
+ if (new_ss[1] & SS_DISABLE) {
+ current_process->ss_sp = 0;
+ current_process->ss_size = 0;
+ current_process->ss_flags = SS_DISABLE;
+ } else {
+ current_process->ss_sp = (uintptr_t)new_ss[0];
+ current_process->ss_flags = new_ss[1];
+ current_process->ss_size = new_ss[2];
+ }
+ }
+ regs->eax = 0;
+ return;
+ }
+
if (syscall_no == SYSCALL_FUTEX) {
#define FUTEX_WAIT 0
#define FUTEX_WAKE 1
int sigsuspend(const uint32_t* mask) {
return __syscall_ret(_syscall1(SYS_SIGSUSPEND, (int)mask));
}
+
+int sigaltstack(const stack_t* ss, stack_t* old_ss) {
+ return __syscall_ret(_syscall2(SYS_SIGALTSTACK, (int)ss, (int)old_ss));
+}