From a44c826d58a1b1e0a2445088429ad5a160e21110 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krystian=20Bac=C5=82awski?= Date: Fri, 28 Jul 2023 22:42:47 +0200 Subject: [PATCH] Extract changes from #1320 that could be commited sooner. --- bin/utest/Makefile | 2 ++ bin/utest/libwrap/xsigaction.c | 10 ++++++ bin/utest/libwrap/xsigprocmask.c | 10 ++++++ bin/utest/signal.c | 55 ++++++++++++++++---------------- bin/utest/utest.h | 6 ++++ bin/utest/util.c | 4 +-- bin/utest/util.h | 4 +++ include/sys/signal.h | 2 +- include/sys/sigtypes.h | 4 +++ lib/libc/gen/sigismember.c | 10 ++++++ sys/kern/signal.c | 8 +++++ sys/kern/syscalls.c | 27 +++++++++++++++- 12 files changed, 111 insertions(+), 31 deletions(-) create mode 100644 bin/utest/libwrap/xsigaction.c create mode 100644 bin/utest/libwrap/xsigprocmask.c create mode 100644 lib/libc/gen/sigismember.c diff --git a/bin/utest/Makefile b/bin/utest/Makefile index 5e89aa20d7..00c77c4eaf 100644 --- a/bin/utest/Makefile +++ b/bin/utest/Makefile @@ -60,6 +60,8 @@ LIBWRAP = \ xsetresgid.c \ xsetresuid.c \ xsignal.c \ + xsigaction.c \ + xsigprocmask.c \ xstat.c \ xsymlink.c \ xunlink.c \ diff --git a/bin/utest/libwrap/xsigaction.c b/bin/utest/libwrap/xsigaction.c new file mode 100644 index 0000000000..f6730c91f9 --- /dev/null +++ b/bin/utest/libwrap/xsigaction.c @@ -0,0 +1,10 @@ +#include "utest.h" +#include + +void xsigaction(int sig, const struct sigaction *restrict act, + struct sigaction *restrict oact) { + int result = sigaction(sig, act, oact); + + if (result < 0) + die("sigaction: %s", strerror(errno)); +} diff --git a/bin/utest/libwrap/xsigprocmask.c b/bin/utest/libwrap/xsigprocmask.c new file mode 100644 index 0000000000..d471ab67e2 --- /dev/null +++ b/bin/utest/libwrap/xsigprocmask.c @@ -0,0 +1,10 @@ +#include "utest.h" +#include + +void xsigprocmask(int how, const sigset_t *restrict set, + sigset_t *restrict oset) { + int result = sigprocmask(how, set, oset); + + if (result < 0) + die("sigprocmask: %s", strerror(errno)); +} diff --git a/bin/utest/signal.c b/bin/utest/signal.c index 7e1d1d8ee4..e512830b12 100644 --- a/bin/utest/signal.c +++ b/bin/utest/signal.c @@ -6,6 +6,7 @@ #include #include #include +#include /* ======= signal_basic ======= */ static volatile int sigusr1_handled = 0; @@ -149,7 +150,7 @@ TEST_ADD(signal_cont_masked, 0) { if (pid == 0) { /* Block SIGCONT. */ sigset_t mask, old; - __sigemptyset(&mask); + sigemptyset(&mask); sigaddset(&mask, SIGCONT); assert(sigprocmask(SIG_BLOCK, &mask, &old) == 0); /* Even though SIGCONT is blocked, it should wake us up, but it @@ -203,7 +204,7 @@ TEST_ADD(signal_mask, 0) { do { sched_yield(); sigpending(&set); - } while (!__sigismember(&set, SIGCONT)); + } while (!sigismember(&set, SIGCONT)); assert(!sigcont_handled); @@ -220,15 +221,15 @@ TEST_ADD(signal_mask, 0) { /* ======= signal_mask_nonmaskable ======= */ TEST_ADD(signal_mask_nonmaskable, 0) { sigset_t set, old; - __sigemptyset(&set); - __sigaddset(&set, SIGSTOP); - __sigaddset(&set, SIGKILL); - __sigaddset(&set, SIGUSR1); + sigemptyset(&set); + sigaddset(&set, SIGSTOP); + sigaddset(&set, SIGKILL); + sigaddset(&set, SIGUSR1); /* The call should succeed, but SIGKILL and SIGSTOP shouldn't be blocked. */ - assert(sigprocmask(SIG_BLOCK, &set, &old) == 0); - assert(sigprocmask(SIG_BLOCK, NULL, &set) == 0); - __sigaddset(&old, SIGUSR1); - assert(__sigsetequal(&set, &old)); + xsigprocmask(SIG_BLOCK, &set, &old); + xsigprocmask(SIG_BLOCK, NULL, &set); + sigaddset(&old, SIGUSR1); + assert(sigsetequal(&set, &old)); return 0; } @@ -238,11 +239,11 @@ TEST_ADD(signal_sigsuspend, 0) { xsignal(SIGCONT, sigcont_handler); xsignal(SIGUSR1, sigusr1_handler); sigset_t set, old; - __sigemptyset(&set); - __sigaddset(&set, SIGCONT); - __sigaddset(&set, SIGUSR1); - assert(sigprocmask(SIG_BLOCK, &set, &old) == 0); - __sigaddset(&old, SIGCONT); + sigemptyset(&set); + sigaddset(&set, SIGCONT); + sigaddset(&set, SIGUSR1); + xsigprocmask(SIG_BLOCK, &set, &old); + sigaddset(&old, SIGCONT); pid_t cpid = xfork(); if (cpid == 0) { for (int i = 0; i < 10; i++) { @@ -255,19 +256,19 @@ TEST_ADD(signal_sigsuspend, 0) { /* Go to sleep with SIGCONT blocked and SIGUSR1 unblocked. */ debug("Calling sigsuspend()..."); sigset_t current; - sigprocmask(SIG_BLOCK, NULL, ¤t); - assert(__sigismember(¤t, SIGUSR1)); - assert(!__sigismember(&old, SIGUSR1)); + xsigprocmask(SIG_BLOCK, NULL, ¤t); + assert(sigismember(¤t, SIGUSR1)); + assert(!sigismember(&old, SIGUSR1)); sigsuspend(&old); /* Check if mask is set back after waking up */ - sigprocmask(SIG_BLOCK, NULL, &set); - assert(__sigsetequal(&set, ¤t)); + xsigprocmask(SIG_BLOCK, NULL, &set); + assert(sigsetequal(&set, ¤t)); /* SIGUSR1 should have woken us up, but SIGCONT should still be pending. */ assert(sigusr1_handled); assert(!sigcont_handled); - __sigemptyset(&set); - __sigaddset(&set, SIGCONT); - assert(sigprocmask(SIG_UNBLOCK, &set, NULL) == 0); + sigemptyset(&set); + sigaddset(&set, SIGCONT); + xsigprocmask(SIG_UNBLOCK, &set, NULL); assert(sigcont_handled); wait_child_finished(cpid); @@ -279,8 +280,8 @@ TEST_ADD(signal_sigsuspend_stop, 0) { pid_t ppid = getpid(); xsignal(SIGUSR1, sigusr1_handler); sigset_t set, old; - __sigemptyset(&set); - __sigaddset(&set, SIGUSR1); + sigemptyset(&set); + sigaddset(&set, SIGUSR1); assert(sigprocmask(SIG_BLOCK, &set, &old) == 0); pid_t cpid = xfork(); if (cpid == 0) { @@ -352,8 +353,8 @@ TEST_ADD(signal_handler_mask, 0) { pid_t ppid = getpid(); struct sigaction sa = {.sa_handler = yield_handler, .sa_flags = 0}; /* Block SIGUSR1 when executing handler for SIGUSR2. */ - __sigemptyset(&sa.sa_mask); - __sigaddset(&sa.sa_mask, SIGUSR1); + sigemptyset(&sa.sa_mask); + sigaddset(&sa.sa_mask, SIGUSR1); assert(sigaction(SIGUSR2, &sa, NULL) == 0); xsignal(SIGUSR1, sigusr1_handler); xsignal(SIGCONT, sigcont_handler); diff --git a/bin/utest/utest.h b/bin/utest/utest.h index f5f5fd4da2..3e1aa2681b 100644 --- a/bin/utest/utest.h +++ b/bin/utest/utest.h @@ -95,9 +95,11 @@ void wait_child_continued(pid_t pid); #include #include +#include typedef void (*sig_t)(int); struct stat; +struct sigaction; struct timezone; struct timeval; @@ -124,6 +126,10 @@ int xopen(const char *path, int flags, ...); void xpipe(int pipefd[2]); void xrmdir(const char *pathname); sig_t xsignal(int sig, sig_t func); +void xsigaction(int sig, const struct sigaction *restrict act, + struct sigaction *restrict oact); +void xsigprocmask(int how, const sigset_t *restrict set, + sigset_t *restrict oset); void xsetgroups(int size, gid_t *list); void xsetresuid(uid_t ruid, uid_t euid, uid_t suid); void xsetresgid(gid_t rgid, gid_t egid, gid_t sgid); diff --git a/bin/utest/util.c b/bin/utest/util.c index b73633fd5c..384f658a35 100644 --- a/bin/utest/util.c +++ b/bin/utest/util.c @@ -43,14 +43,14 @@ static void noop_handler(int signo) { void signal_setup(int signo) { xsignal(signo, noop_handler); sigset_t mask; - __sigemptyset(&mask); + sigemptyset(&mask); sigaddset(&mask, signo); assert(sigprocmask(SIG_BLOCK, &mask, NULL) == 0); } void wait_for_signal(int signo) { sigset_t mask; - __sigfillset(&mask); + sigfillset(&mask); sigdelset(&mask, signo); sigsuspend(&mask); } diff --git a/bin/utest/util.h b/bin/utest/util.h index 553679623a..648e255bc4 100644 --- a/bin/utest/util.h +++ b/bin/utest/util.h @@ -6,6 +6,10 @@ #include #include +static inline int sigsetequal(sigset_t *a, sigset_t *b) { + return memcmp(a, b, sizeof(sigset_t)) == 0; +} + /* Do the necessary setup needed to wait for the signal. * Must be called before receiving the signal, * ideally at the very beginning of the test procedure. */ diff --git a/include/sys/signal.h b/include/sys/signal.h index 25030e8795..7077d24d7a 100644 --- a/include/sys/signal.h +++ b/include/sys/signal.h @@ -203,7 +203,7 @@ int do_sigaction(signo_t sig, const sigaction_t *act, sigaction_t *oldact); int do_sigprocmask(int how, const sigset_t *set, sigset_t *oset); int do_sigsuspend(proc_t *p, const sigset_t *mask); int do_sigpending(proc_t *p, sigset_t *set); -int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *kinfo, +int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *ksi, struct timespec *timeout); #endif /* !_KERNEL */ diff --git a/include/sys/sigtypes.h b/include/sys/sigtypes.h index 36c04d467c..8766f37c29 100644 --- a/include/sys/sigtypes.h +++ b/include/sys/sigtypes.h @@ -15,6 +15,8 @@ typedef struct { uint32_t __bits; /* bit 0 is unused */ } sigset_t; +#if defined(_KERNEL) || defined(_LIBC) + /* * Macro for manipulating signal masks. */ @@ -33,6 +35,8 @@ typedef struct { { (t)->__bits &= (s)->__bits; } #define __sigfindset(s) (__builtin_ffs((s)->__bits)) +#endif /* !_KERNEL */ + typedef struct sigaltstack { void *ss_sp; /* signal stack base */ size_t ss_size; /* signal stack length */ diff --git a/lib/libc/gen/sigismember.c b/lib/libc/gen/sigismember.c new file mode 100644 index 0000000000..0a38aa5f14 --- /dev/null +++ b/lib/libc/gen/sigismember.c @@ -0,0 +1,10 @@ +#include +#include + +int sigismember(const sigset_t *set, int signo) { + if (signo <= 0 || signo >= NSIG) { + errno = EINVAL; + return -1; + } + return (__sigismember(set, signo)); +} diff --git a/sys/kern/signal.c b/sys/kern/signal.c index 4195fba973..63eb1c42a0 100644 --- a/sys/kern/signal.c +++ b/sys/kern/signal.c @@ -13,6 +13,9 @@ #include #include +#include +#include + static KMALLOC_DEFINE(M_SIGNAL, "signal"); /*!\brief Signal properties. */ @@ -201,6 +204,11 @@ int do_sigsuspend(proc_t *p, const sigset_t *mask) { return ERESTARTNOHAND; } +int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *ksi, + timespec_t *tsp) { + return ENOTSUP; +} + int do_sigpending(proc_t *p, sigset_t *set) { SCOPED_MTX_LOCK(&p->p_lock); thread_t *td = p->p_thread; diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index 0cb9069a7c..13f0faab32 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -1333,7 +1333,32 @@ static int sys_kevent(proc_t *p, kevent_args_t *args, register_t *res) { static int sys_sigtimedwait(proc_t *p, sigtimedwait_args_t *args, register_t *res) { - return ENOTSUP; + const sigset_t *u_set = SCARG(args, set); + siginfo_t *u_info = SCARG(args, info); + const timespec_t *u_timeout = SCARG(args, timeout); + sigset_t set; + ksiginfo_t ksi; + timespec_t timeout = {}; + int error; + + if (u_timeout) { + error = copyin_s(u_timeout, timeout); + if (error) + return error; + } + + if ((error = copyin_s(u_set, set))) + return error; + + if ((error = do_sigtimedwait(p, set, &ksi, u_timeout ? &timeout : NULL))) + return error; + + if (u_info) + error = copyout_s(ksi.ksi_info, u_info); + + *res = ksi.ksi_info.si_signo; + + return error; } static int sys_clock_settime(proc_t *p, clock_settime_args_t *args,