diff options
| author | Mark Brown <broonie@kernel.org> | 2026-10-20 14:37:19 +0100 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2026-10-20 14:37:19 +0100 |
| commit | 99722ee7af41b7fd65c842bb90d16c9722563ec4 (patch) | |
| tree | b532dd1925f79cfa9ce074835bbf9ba7e3d950ce /kernel | |
| parent | b08f9fed02fa5614bc743fc9008cc9f0cd4f2807 (diff) | |
| parent | e32008340585a12783045c4426fbb963cfa11b7e (diff) | |
| download | linux-next-99722ee7af41b7fd65c842bb90d16c9722563ec4.tar.gz linux-next-99722ee7af41b7fd65c842bb90d16c9722563ec4.zip | |
Merge branch 'for-next/seccomp' of https://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/seccomp.c | 26 |
1 files changed, 19 insertions, 7 deletions
diff --git a/kernel/seccomp.c b/kernel/seccomp.c index 86cf4460d69e..3eecba5ccdef 100644 --- a/kernel/seccomp.c +++ b/kernel/seccomp.c @@ -205,6 +205,7 @@ static inline void seccomp_cache_prepare(struct seccomp_filter *sfilter) * @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. + * @restart_before_recv: Restart interrupted syscalls before notification receipt. * @prev: points to a previously installed, or inherited, filter * @prog: the BPF program to evaluate * @notif: the struct that holds all notification related information @@ -226,6 +227,7 @@ struct seccomp_filter { refcount_t users; bool log; bool wait_killable_recv; + bool restart_before_recv; struct action_cache cache; struct seccomp_filter *prev; struct bpf_prog *prog; @@ -953,6 +955,8 @@ static long seccomp_attach_filter(unsigned int flags, /* Set wait killable flag, if present. */ if (flags & SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV) filter->wait_killable_recv = true; + if (flags & SECCOMP_FILTER_FLAG_RESTART_BEFORE_RECV) + filter->restart_before_recv = true; /* * If there is an existing filter, make it the prev and don't drop its @@ -1208,8 +1212,12 @@ static int seccomp_do_user_notification(int this_syscall, * Check to see whether we should switch to wait * killable. Only return the interrupted error if not. */ - if (!(!wait_killable && should_sleep_killable(match, &n))) + if (!(!wait_killable && should_sleep_killable(match, &n))) { + if (err == -ERESTARTSYS && match->restart_before_recv && + n.state == SECCOMP_NOTIFY_INIT) + err = -ERESTARTNOINTR; goto interrupted; + } } addfd = list_first_entry_or_null(&n.addfd, @@ -1735,7 +1743,8 @@ static long seccomp_notify_addfd(struct seccomp_filter *filter, if (addfd.newfd && !(addfd.flags & SECCOMP_ADDFD_FLAG_SETFD)) return -EINVAL; - kaddfd.file = fget(addfd.srcfd); + /* Allow O_PATH files, as SCM_RIGHTS and pidfd_getfd() do. */ + kaddfd.file = fget_raw(addfd.srcfd); if (!kaddfd.file) return -EBADF; @@ -1808,10 +1817,13 @@ static long seccomp_notify_addfd(struct seccomp_filter *filter, * We need to check again if the addfd request has been handled, * and if not, we will remove it from the queue. */ - if (list_empty(&kaddfd.list)) + if (list_empty(&kaddfd.list)) { ret = kaddfd.ret; - else + } else { list_del(&kaddfd.list); + if (addfd.flags & SECCOMP_ADDFD_FLAG_SEND) + knotif->state = SECCOMP_NOTIFY_SENT; + } out_unlock: mutex_unlock(&filter->notify_lock); @@ -1977,10 +1989,10 @@ static long seccomp_set_mode_filter(unsigned int flags, return -EINVAL; /* - * The SECCOMP_FILTER_FLAG_WAIT_KILLABLE_SENT flag doesn't make sense - * without the SECCOMP_FILTER_FLAG_NEW_LISTENER flag. + * Notification wait flags require a userspace listener. */ - if ((flags & SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV) && + if ((flags & (SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV | + SECCOMP_FILTER_FLAG_RESTART_BEFORE_RECV)) && ((flags & SECCOMP_FILTER_FLAG_NEW_LISTENER) == 0)) return -EINVAL; |
