From nobody Mon Jun 15 12:36:20 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7DFDDC433F5 for ; Fri, 29 Apr 2022 02:32:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233729AbiD2Cfo (ORCPT ); Thu, 28 Apr 2022 22:35:44 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39588 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229958AbiD2Cfm (ORCPT ); Thu, 28 Apr 2022 22:35:42 -0400 Received: from mail-pj1-x1033.google.com (mail-pj1-x1033.google.com [IPv6:2607:f8b0:4864:20::1033]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 52246381AD for ; Thu, 28 Apr 2022 19:32:25 -0700 (PDT) Received: by mail-pj1-x1033.google.com with SMTP id e24so5934558pjt.2 for ; Thu, 28 Apr 2022 19:32:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sargun.me; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=KKxse1EuoQRIJFpeXhFntqj/7Oiw8PNwIrLabygRLiI=; b=DNYsLfLWyo1bax7iYZ7M3li6izMSXd9t+VrBQBR6Tkg8ghCcsQPIVYDEmQtowx9r43 auX3pf/lUt1qP/UrOr063u7uRWkkYafsuY5TsPwpJPV/rLavvkmRON0VLUwb4TH1YUO/ vNDq6vSyehrTbYGVLNnkLyTkxOTib2Vb32cDU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=KKxse1EuoQRIJFpeXhFntqj/7Oiw8PNwIrLabygRLiI=; b=vM1KTR5Zp97l8fWRxq2d48EuIJX4rlNWDUTTJAcm3VK/ElUUCFqhS4uYFCz7x8Rq2i XyKWMWRknd7F5vhR2+jwaCl2STgoUXEYO324oWGGPh6DD6SDqdmtCIumWJaonYdhzATQ f4I9QDxkeBoJgP7xMb1pNygWSbZCF/Id4GY9UlttvT2mvSrFVwLRLIrashahfRFWfLBL Z9a5UvQvp4c07FeJGJKMEu2ZzyeOJpwL6lGdKIBXEX7UwdNO+g2Ug9+5Uajc/fDtC/xy v9NpofvcrYg5PE+uIsFL/IM+vNZm4FeaBvkTVDj2AJKiejvamAQEyDfXX4zdW/n4auvE XdiQ== X-Gm-Message-State: AOAM530W5AxeZ0Le9IVBszMyeSIkKvsbRbjNvZPzlgkbI4tRZAUk+MTh CvW1El4F+r79/8klSIV4hp2dGg== X-Google-Smtp-Source: ABdhPJwitGysMkBtPTmF1N3j2QNma3jVr62lw8m5WG3tZNB3NTmZZanOWkX52vskHT68O2yebVu1vA== X-Received: by 2002:a17:902:988f:b0:15b:8195:5199 with SMTP id s15-20020a170902988f00b0015b81955199mr36865948plp.96.1651199544428; Thu, 28 Apr 2022 19:32:24 -0700 (PDT) Received: from localhost.localdomain (99-0-82-137.lightspeed.sntcca.sbcglobal.net. [99.0.82.137]) by smtp.gmail.com with ESMTPSA id g5-20020a17090a640500b001cd4989ff53sm8201125pjj.26.2022.04.28.19.32.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Apr 2022 19:32:23 -0700 (PDT) From: Sargun Dhillon To: Kees Cook , LKML , Linux Containers Cc: Sargun Dhillon , Rodrigo Campos , Christian Brauner , Giuseppe Scrivano , Will Drewry , Andy Lutomirski , Alban Crequy Subject: [PATCH v3 1/2] seccomp: Add wait_killable semantic to seccomp user notifier Date: Thu, 28 Apr 2022 19:31:12 -0700 Message-Id: <20220429023113.74993-2-sargun@sargun.me> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220429023113.74993-1-sargun@sargun.me> References: <20220429023113.74993-1-sargun@sargun.me> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" This introduces a per-filter flag (SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV) that makes it so that when notifications are received by the supervisor the notifying process will transition to wait killable semantics. Although wait killable isn't a set of semantics formally exposed to userspace, the concept is searchable. If the notifying process is signaled prior to the notification being received by the userspace agent, it will be handled as normal. One quirk about how this is handled is that the notifying process only switches to TASK_KILLABLE if it receives a wakeup from either an addfd or a signal. This is to avoid an unnecessary wakeup of the notifying task. Signed-off-by: Sargun Dhillon --- .../userspace-api/seccomp_filter.rst | 8 ++++ include/linux/seccomp.h | 3 +- include/uapi/linux/seccomp.h | 2 + kernel/seccomp.c | 42 ++++++++++++++++++- 4 files changed, 52 insertions(+), 3 deletions(-) diff --git a/Documentation/userspace-api/seccomp_filter.rst b/Documentation= /userspace-api/seccomp_filter.rst index 539e9d4a4860..204cf5ba511a 100644 --- a/Documentation/userspace-api/seccomp_filter.rst +++ b/Documentation/userspace-api/seccomp_filter.rst @@ -271,6 +271,14 @@ notifying process it will be replaced. The supervisor = can also add an FD, and respond atomically by using the ``SECCOMP_ADDFD_FLAG_SEND`` flag and the r= eturn value will be the injected file descriptor number. =20 +The notifying process can be preempted, resulting in the notification being +aborted. This can be problematic when trying to take actions on behalf of = the +notifying process that are long-running and typically retryable (mounting a +filesytem). Alternatively, the at filter installation time, the +``SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV`` flag can be set. This flag make= s it +such that when a user notification is received by the supervisor, the noti= fying +process will ignore non-fatal signals until the response is sent. + It is worth noting that ``struct seccomp_data`` contains the values of reg= ister arguments to the syscall, but does not contain pointers to memory. The tas= k's memory is accessible to suitably privileged traces via ``ptrace()`` or diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h index 0c564e5d40ff..d31d76be4982 100644 --- a/include/linux/seccomp.h +++ b/include/linux/seccomp.h @@ -8,7 +8,8 @@ SECCOMP_FILTER_FLAG_LOG | \ SECCOMP_FILTER_FLAG_SPEC_ALLOW | \ SECCOMP_FILTER_FLAG_NEW_LISTENER | \ - SECCOMP_FILTER_FLAG_TSYNC_ESRCH) + SECCOMP_FILTER_FLAG_TSYNC_ESRCH | \ + SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV) =20 /* sizeof() the first published struct seccomp_notif_addfd */ #define SECCOMP_NOTIFY_ADDFD_SIZE_VER0 24 diff --git a/include/uapi/linux/seccomp.h b/include/uapi/linux/seccomp.h index 78074254ab98..0fdc6ef02b94 100644 --- a/include/uapi/linux/seccomp.h +++ b/include/uapi/linux/seccomp.h @@ -23,6 +23,8 @@ #define SECCOMP_FILTER_FLAG_SPEC_ALLOW (1UL << 2) #define SECCOMP_FILTER_FLAG_NEW_LISTENER (1UL << 3) #define SECCOMP_FILTER_FLAG_TSYNC_ESRCH (1UL << 4) +/* Received notifications wait in killable state (only respond to fatal si= gnals) */ +#define SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV (1UL << 5) =20 /* * All BPF programs must return a 32-bit value. diff --git a/kernel/seccomp.c b/kernel/seccomp.c index db10e73d06e0..9291b0843cb2 100644 --- a/kernel/seccomp.c +++ b/kernel/seccomp.c @@ -201,6 +201,8 @@ static inline void seccomp_cache_prepare(struct seccomp= _filter *sfilter) * the filter can be freed. * @cache: cache of arch/syscall mappings to actions * @log: true if all actions except for SECCOMP_RET_ALLOW should be logged + * @wait_killable_recv: Put notifying process in killable state once the + * notification is received by the userspace listener. * @prev: points to a previously installed, or inherited, filter * @prog: the BPF program to evaluate * @notif: the struct that holds all notification related information @@ -221,6 +223,7 @@ struct seccomp_filter { refcount_t refs; refcount_t users; bool log; + bool wait_killable_recv; struct action_cache cache; struct seccomp_filter *prev; struct bpf_prog *prog; @@ -894,6 +897,10 @@ static long seccomp_attach_filter(unsigned int flags, if (flags & SECCOMP_FILTER_FLAG_LOG) filter->log =3D true; =20 + /* Set wait killable flag, if present. */ + if (flags & SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV) + filter->wait_killable_recv =3D true; + /* * If there is an existing filter, make it the prev and don't drop its * task reference. @@ -1081,6 +1088,12 @@ static void seccomp_handle_addfd(struct seccomp_kadd= fd *addfd, struct seccomp_kn complete(&addfd->completion); } =20 +static bool should_sleep_killable(struct seccomp_filter *match, + struct seccomp_knotif *n) +{ + return match->wait_killable_recv && n->state =3D=3D SECCOMP_NOTIFY_SENT; +} + static int seccomp_do_user_notification(int this_syscall, struct seccomp_filter *match, const struct seccomp_data *sd) @@ -1111,11 +1124,25 @@ static int seccomp_do_user_notification(int this_sy= scall, * This is where we wait for a reply from userspace. */ do { + bool wait_killable =3D should_sleep_killable(match, &n); + mutex_unlock(&match->notify_lock); - err =3D wait_for_completion_interruptible(&n.ready); + if (wait_killable) + err =3D wait_for_completion_killable(&n.ready); + else + err =3D wait_for_completion_interruptible(&n.ready); mutex_lock(&match->notify_lock); - if (err !=3D 0) + + if (err !=3D 0) { + /* + * Check to see if the notifcation got picked up and + * whether we should switch to wait killable. + */ + if (!wait_killable && should_sleep_killable(match, &n)) + continue; + goto interrupted; + } =20 addfd =3D list_first_entry_or_null(&n.addfd, struct seccomp_kaddfd, list); @@ -1485,6 +1512,9 @@ static long seccomp_notify_recv(struct seccomp_filter= *filter, mutex_lock(&filter->notify_lock); knotif =3D find_notification(filter, unotif.id); if (knotif) { + /* Reset the process to make sure it's not stuck */ + if (should_sleep_killable(filter, knotif)) + complete(&knotif->ready); knotif->state =3D SECCOMP_NOTIFY_INIT; up(&filter->notif->request); } @@ -1830,6 +1860,14 @@ static long seccomp_set_mode_filter(unsigned int fla= gs, ((flags & SECCOMP_FILTER_FLAG_TSYNC_ESRCH) =3D=3D 0)) return -EINVAL; =20 + /* + * The SECCOMP_FILTER_FLAG_WAIT_KILLABLE_SENT flag doesn't make sense + * without the SECCOMP_FILTER_FLAG_NEW_LISTENER flag. + */ + if ((flags & SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV) && + ((flags & SECCOMP_FILTER_FLAG_NEW_LISTENER) =3D=3D 0)) + return -EINVAL; + /* Prepare the new filter before holding any locks. */ prepared =3D seccomp_prepare_user_filter(filter); if (IS_ERR(prepared)) --=20 2.25.1 From nobody Mon Jun 15 12:36:20 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1E66BC433F5 for ; Fri, 29 Apr 2022 02:32:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234207AbiD2Cfs (ORCPT ); Thu, 28 Apr 2022 22:35:48 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39652 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229958AbiD2Cfo (ORCPT ); Thu, 28 Apr 2022 22:35:44 -0400 Received: from mail-pj1-x1035.google.com (mail-pj1-x1035.google.com [IPv6:2607:f8b0:4864:20::1035]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 62A46BE9D7 for ; Thu, 28 Apr 2022 19:32:27 -0700 (PDT) Received: by mail-pj1-x1035.google.com with SMTP id e24so5934607pjt.2 for ; Thu, 28 Apr 2022 19:32:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sargun.me; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=pD7wEVjDWCs0OWLvmcopLdOCLaRUm5C47DNo4B3Tw7U=; b=xj8lZ+yr9k3J3mFn8VQz4YUpZJzODslf4C3U180V6cjAWmNfZaXaNGaTYLltHnvbTa UXBkEmkneUfjnGAZ0U/xhCYJgHMU8MsfGGxmEEHQXXjyqNN+3L96zR2bBycECwSA5Kju qI4nGwDNCET/RYssmMZol8OAVBESEBjpZrUsE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=pD7wEVjDWCs0OWLvmcopLdOCLaRUm5C47DNo4B3Tw7U=; b=GjVbpYN5zJrYUYJLTVP3dNgxwkgi3q4UYDa3dmZ3WlrI9KNOID7qz6Zvd2D6+90s46 T+4/EJXbUHl7IcXp8v9tTBi55bqw/zuSF+QwgYjn6OSoGLjDBSWb7lOQl98dz5Xg69Y9 nnHfysDl8Y49heeDfdaJvme0o4izTFomOkWqWHb+DLv1bza6pUHyvbNuX2sOnPxouvuz GRCrlcLzTIDUGo2RkhCIgIS67G4LNBE3/IicqUlpHxXHapCwQgGgLAzfWM5WniJO0Bbs RN2Xx8eyJ7LppEzACC13KcWl+aV5YDRYUKVD1BRrthi3zF4nzsuo3+LnYwSXC6znTCNY xj0Q== X-Gm-Message-State: AOAM531yY3GqPf0ONwopDIzssdgX2WG7Mh7cRJRVA+4clgSObBTUMB1z fkrIiBg/JpMel8VHoWBlAT9ffQ== X-Google-Smtp-Source: ABdhPJzNRCcH4nTJk7D57es2Ky8PAPBoVWour/2NQe5p7BOqVE+Y/3nfIGdt3+YQG55ZFG4v8nGGEw== X-Received: by 2002:a17:902:c2c3:b0:15c:fd3c:7a9b with SMTP id c3-20020a170902c2c300b0015cfd3c7a9bmr26316227pla.31.1651199546488; Thu, 28 Apr 2022 19:32:26 -0700 (PDT) Received: from localhost.localdomain (99-0-82-137.lightspeed.sntcca.sbcglobal.net. [99.0.82.137]) by smtp.gmail.com with ESMTPSA id g5-20020a17090a640500b001cd4989ff53sm8201125pjj.26.2022.04.28.19.32.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Apr 2022 19:32:25 -0700 (PDT) From: Sargun Dhillon To: Kees Cook , LKML , Linux Containers Cc: Sargun Dhillon , Rodrigo Campos , Christian Brauner , Giuseppe Scrivano , Will Drewry , Andy Lutomirski , Alban Crequy Subject: [PATCH v3 2/2] selftests/seccomp: Add test for wait killable notifier Date: Thu, 28 Apr 2022 19:31:13 -0700 Message-Id: <20220429023113.74993-3-sargun@sargun.me> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220429023113.74993-1-sargun@sargun.me> References: <20220429023113.74993-1-sargun@sargun.me> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" This verifies that if a filter is set up with the wait killable feature that it obeys the semantics that non-fatal signals are ignored during a notification after the notification is received. Cases tested: * Non-fatal signal prior to receive * Non-fatal signal during receive * Fatal signal after receive The pre-receive signal handling is tested elsewhere, and that codepath remains unchanged. Signed-off-by: Sargun Dhillon --- tools/testing/selftests/seccomp/seccomp_bpf.c | 240 ++++++++++++++++++ 1 file changed, 240 insertions(+) diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c b/tools/testing/= selftests/seccomp/seccomp_bpf.c index 9d126d7fabdb..825b179b6751 100644 --- a/tools/testing/selftests/seccomp/seccomp_bpf.c +++ b/tools/testing/selftests/seccomp/seccomp_bpf.c @@ -59,6 +59,8 @@ #define SKIP(s, ...) XFAIL(s, ##__VA_ARGS__) #endif =20 +#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) + #ifndef PR_SET_PTRACER # define PR_SET_PTRACER 0x59616d61 #endif @@ -268,6 +270,10 @@ struct seccomp_notif_addfd_big { #define SECCOMP_FILTER_FLAG_TSYNC_ESRCH (1UL << 4) #endif =20 +#ifndef SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV +#define SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV (1UL << 5) +#endif + #ifndef seccomp int seccomp(unsigned int op, unsigned int flags, void *args) { @@ -4231,6 +4237,240 @@ TEST(user_notification_addfd_rlimit) close(memfd); } =20 +static char get_proc_stat(int pid) +{ + char proc_path[100] =3D { 0 }; + char *line =3D NULL; + size_t len =3D 0; + ssize_t nread; + char status; + FILE *f; + int i; + + snprintf(proc_path, sizeof(proc_path), "/proc/%d/stat", pid); + f =3D fopen(proc_path, "r"); + if (f =3D=3D NULL) + ksft_exit_fail_msg("%s - Could not open %s\n", strerror(errno), + proc_path); + + for (i =3D 0; i < 3; i++) { + nread =3D getdelim(&line, &len, ' ', f); + if (nread <=3D 0) + ksft_exit_fail_msg("Failed to read status: %s\n", + strerror(errno)); + } + + status =3D *line; + free(line); + fclose(f); + + return status; +} + +/* Returns -1 if not in syscall (running or blocked) */ +static long get_proc_syscall(int pid) +{ + char proc_path[100] =3D { 0 }; + char *line =3D NULL; + size_t len =3D 0; + ssize_t nread; + long ret =3D -1; + FILE *f; + + snprintf(proc_path, sizeof(proc_path), "/proc/%d/syscall", pid); + f =3D fopen(proc_path, "r"); + if (f =3D=3D NULL) + ksft_exit_fail_msg("%s - Could not open %s\n", strerror(errno), + proc_path); + + nread =3D getdelim(&line, &len, ' ', f); + if (nread <=3D 0) + ksft_exit_fail_msg("Failed to read status: %s\n", + strerror(errno)); + + if (!strncmp("running", line, MIN(7, nread))) + ret =3D strtol(line, NULL, 16); + + free(line); + fclose(f); + + return ret; +} + +TEST(user_notification_wait_killable_pre_notification) +{ + struct sigaction new_action =3D { + .sa_handler =3D signal_handler, + }; + int listener, status, sk_pair[2]; + pid_t pid; + long ret; + char c; + /* 100 ms */ + struct timespec delay =3D { .tv_nsec =3D 100000000 }; + + ASSERT_EQ(sigemptyset(&new_action.sa_mask), 0); + + ret =3D prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); + ASSERT_EQ(0, ret) { + TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!"); + } + + ASSERT_EQ(socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sk_pair), 0); + + + listener =3D user_notif_syscall(__NR_getppid, + SECCOMP_FILTER_FLAG_NEW_LISTENER | + SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV); + ASSERT_GE(listener, 0); + + /* + * Check that we can kill the process with SIGUSR1 prior to receiving + * the notification. SIGUSR1 is wired up to a custom signal handler, + * and make sure it gets called. + */ + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + close(sk_pair[0]); + handled =3D sk_pair[1]; + + /* Setup the sigaction without SA_RESTART */ + if (sigaction(SIGUSR1, &new_action, NULL)) { + perror("sigaction"); + exit(1); + } + + ret =3D syscall(__NR_getppid); + exit(ret !=3D -1 || errno !=3D EINTR); + } + + while (get_proc_syscall(pid) !=3D __NR_getppid && + get_proc_stat(pid) !=3D 'S') + nanosleep(&delay, NULL); + + EXPECT_EQ(kill(pid, SIGUSR1), 0); + + EXPECT_EQ(waitpid(pid, &status, 0), pid); + EXPECT_EQ(true, WIFEXITED(status)); + EXPECT_EQ(0, WEXITSTATUS(status)); + + EXPECT_EQ(read(sk_pair[0], &c, 1), 1); +} + +TEST(user_notification_wait_killable) +{ + struct sigaction new_action =3D { + .sa_handler =3D signal_handler, + }; + struct seccomp_notif_resp resp =3D {}; + struct seccomp_notif req =3D {}; + int listener, status, sk_pair[2]; + pid_t pid; + long ret; + char c; + /* 100 ms */ + struct timespec delay =3D { .tv_nsec =3D 100000000 }; + + ASSERT_EQ(sigemptyset(&new_action.sa_mask), 0); + + ret =3D prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); + ASSERT_EQ(0, ret) { + TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!"); + } + + ASSERT_EQ(socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sk_pair), 0); + + listener =3D user_notif_syscall(__NR_getppid, + SECCOMP_FILTER_FLAG_NEW_LISTENER | + SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV); + ASSERT_GE(listener, 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + close(sk_pair[0]); + handled =3D sk_pair[1]; + + /* Setup the sigaction without SA_RESTART */ + if (sigaction(SIGUSR1, &new_action, NULL)) { + perror("sigaction"); + exit(1); + } + + /* Make sure that the syscall is completed (no EINTR) */ + ret =3D syscall(__NR_getppid); + exit(ret !=3D USER_NOTIF_MAGIC); + } + + while (get_proc_syscall(pid) !=3D __NR_getppid && + get_proc_stat(pid) !=3D 'S') + nanosleep(&delay, NULL); + + EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, &req), 0); + /* Kill the process to make sure it enters the wait_killable state */ + EXPECT_EQ(kill(pid, SIGUSR1), 0); + + /* TASK_KILLABLE is considered D (Disk Sleep) state */ + while (get_proc_stat(pid) !=3D 'D') + nanosleep(&delay, NULL); + + resp.id =3D req.id; + resp.val =3D USER_NOTIF_MAGIC; + EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_SEND, &resp), 0); + + /* + * Make sure that the signal handler does get called once we're back in + * userspace. + */ + EXPECT_EQ(read(sk_pair[0], &c, 1), 1); + EXPECT_EQ(waitpid(pid, &status, 0), pid); + EXPECT_EQ(true, WIFEXITED(status)); + EXPECT_EQ(0, WEXITSTATUS(status)); +} + +TEST(user_notification_wait_killable_fatal) +{ + struct seccomp_notif req =3D {}; + int listener, status; + pid_t pid; + long ret; + /* 100 ms */ + struct timespec delay =3D { .tv_nsec =3D 100000000 }; + + ret =3D prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); + ASSERT_EQ(0, ret) { + TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!"); + } + + listener =3D user_notif_syscall(__NR_getppid, + SECCOMP_FILTER_FLAG_NEW_LISTENER | + SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV); + ASSERT_GE(listener, 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + /* This should never complete */ + syscall(__NR_getppid); + exit(1); + } + + while (get_proc_stat(pid) !=3D 'S') + nanosleep(&delay, NULL); + + EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, &req), 0); + /* Kill the process with a fatal signal */ + EXPECT_EQ(kill(pid, SIGTERM), 0); + + EXPECT_EQ(waitpid(pid, &status, 0), pid); + EXPECT_EQ(true, WIFSIGNALED(status)); + EXPECT_EQ(SIGTERM, WTERMSIG(status)); +} + /* * TODO: * - expand NNP testing --=20 2.25.1