From 8066e8f1d82503834847b25543e556e774396135 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 10 Jul 2023 21:01:59 +0200 Subject: [PATCH] kernel+libc: Implement sigprocmask() and friends --- kernel/src/sys/signal.cpp | 31 ++++++++++++++++++++ libc/include/bits/signal.h | 5 ++++ libc/include/signal.h | 18 ++++++++++++ libc/src/signal.cpp | 53 ++++++++++++++++++++++++++++++++++ libluna/include/luna/Syscall.h | 2 +- 5 files changed, 108 insertions(+), 1 deletion(-) diff --git a/kernel/src/sys/signal.cpp b/kernel/src/sys/signal.cpp index 864fd1f8..e81952a0 100644 --- a/kernel/src/sys/signal.cpp +++ b/kernel/src/sys/signal.cpp @@ -2,6 +2,7 @@ #include "memory/MemoryManager.h" #include "sys/Syscall.h" #include "thread/Scheduler.h" +#include Result sys_sigreturn(Registers* regs, SyscallArgs) { @@ -66,3 +67,33 @@ Result sys_kill(Registers*, SyscallArgs args) return 0; } + +Result sys_sigprocmask(Registers*, SyscallArgs args) +{ + auto* current = Scheduler::current(); + + int how = (int)args[0]; + const sigset_t* set = (const sigset_t*)args[1]; + sigset_t* oldset = (sigset_t*)args[2]; + + if (oldset) + { + if (!MemoryManager::copy_to_user_typed(oldset, ¤t->signal_mask)) return err(EFAULT); + } + + if (set) + { + sigset_t kset; + if (!MemoryManager::copy_from_user_typed(set, &kset)) return err(EFAULT); + + switch (how) + { + case SIG_BLOCK: current->signal_mask |= kset; + case SIG_UNBLOCK: current->signal_mask &= ~kset; + case SIG_SETMASK: current->signal_mask = kset; + default: return err(EINVAL); + } + } + + return 0; +} diff --git a/libc/include/bits/signal.h b/libc/include/bits/signal.h index 9cc47724..2cf92f99 100644 --- a/libc/include/bits/signal.h +++ b/libc/include/bits/signal.h @@ -18,6 +18,11 @@ struct sigaction void* __sa_sigreturn = nullptr; }; +// Constants for the 'how' parameter in sigprocmask(). +#define SIG_BLOCK 0 +#define SIG_UNBLOCK 1 +#define SIG_SETMASK 2 + // The signals with explicit numbers have portable signal numbers. enum __signals { diff --git a/libc/include/signal.h b/libc/include/signal.h index b12ccb80..3cfa36cf 100644 --- a/libc/include/signal.h +++ b/libc/include/signal.h @@ -25,6 +25,24 @@ extern "C" /* Send a signal to the current thread. */ int raise(int signo); + /* Modify the current thread's signal mask. */ + int sigprocmask(int how, const sigset_t* set, sigset_t* oldset); + + /* Clear all signals from set. */ + int sigemptyset(sigset_t* set); + + /* Add all signals to set. */ + int sigfillset(sigset_t* set); + + /* Add a specific signal to set. */ + int sigaddset(sigset_t* set, int signo); + + /* Remove a specific signal from set. */ + int sigdelset(sigset_t* set, int signo); + + /* Check if a signal is in set.*/ + int sigismember(const sigset_t* set, int signo); + #ifdef __cplusplus } #endif diff --git a/libc/src/signal.cpp b/libc/src/signal.cpp index 07455bdd..9b55e78b 100644 --- a/libc/src/signal.cpp +++ b/libc/src/signal.cpp @@ -23,4 +23,57 @@ extern "C" { return kill(getpid(), signo); } + + int sigprocmask(int how, const sigset_t* set, sigset_t* oldset) + { + long rc = syscall(SYS_sigprocmask, how, set, oldset); + __errno_return(rc, int); + } + + int sigemptyset(sigset_t* set) + { + *set = 0; + return 0; + } + + int sigfillset(sigset_t* set) + { + *set = 0xffffffff; + return 0; + } + + int sigaddset(sigset_t* set, int signo) + { + if (signo <= 0 || signo > NSIG) + { + errno = EINVAL; + return -1; + } + + *set |= (1 << (signo - 1)); + return 0; + } + + int sigdelset(sigset_t* set, int signo) + { + if (signo <= 0 || signo > NSIG) + { + errno = EINVAL; + return -1; + } + + *set &= ~(1 << (signo - 1)); + return 0; + } + + int sigismember(const sigset_t* set, int signo) + { + if (signo <= 0 || signo > NSIG) + { + errno = EINVAL; + return -1; + } + + return (*set & (1 << (signo - 1))) > 0; + } } diff --git a/libluna/include/luna/Syscall.h b/libluna/include/luna/Syscall.h index 93db68ab..c89beb66 100644 --- a/libluna/include/luna/Syscall.h +++ b/libluna/include/luna/Syscall.h @@ -6,7 +6,7 @@ _e(getgid) _e(getegid) _e(setuid) _e(setgid) _e(seteuid) _e(setegid) _e(fchmodat) _e(fchownat) _e(ioctl) \ _e(fstatat) _e(chdir) _e(getcwd) _e(unlinkat) _e(uname) _e(sethostname) _e(dup2) _e(pipe) _e(mount) \ _e(umount) _e(pstat) _e(getrusage) _e(symlinkat) _e(readlinkat) _e(umask) _e(linkat) _e(faccessat) \ - _e(pivot_root) _e(sigreturn) _e(sigaction) _e(kill) + _e(pivot_root) _e(sigreturn) _e(sigaction) _e(kill) _e(sigprocmask) enum Syscalls {