Skip to content

Commit ddc4739

Browse files
sargunkees
authored andcommitted
seccomp: Refactor notification handler to prepare for new semantics
This refactors the user notification code to have a do / while loop around the completion condition. This has a small change in semantic, in that previously we ignored addfd calls upon wakeup if the notification had been responded to, but instead with the new change we check for an outstanding addfd calls prior to returning to userspace. Rodrigo Campos also identified a bug that can result in addfd causing an early return, when the supervisor didn't actually handle the syscall [1]. [1]: https://lore.kernel.org/lkml/[email protected]/ Fixes: 7cf97b1 ("seccomp: Introduce addfd ioctl to seccomp user notifier") Signed-off-by: Sargun Dhillon <[email protected]> Acked-by: Tycho Andersen <[email protected]> Acked-by: Christian Brauner <[email protected]> Signed-off-by: Kees Cook <[email protected]> Tested-by: Rodrigo Campos <[email protected]> Cc: [email protected] Link: https://lore.kernel.org/r/[email protected]
1 parent aac9029 commit ddc4739

File tree

1 file changed

+16
-14
lines changed

1 file changed

+16
-14
lines changed

kernel/seccomp.c

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,28 +1105,30 @@ static int seccomp_do_user_notification(int this_syscall,
11051105

11061106
up(&match->notif->request);
11071107
wake_up_poll(&match->wqh, EPOLLIN | EPOLLRDNORM);
1108-
mutex_unlock(&match->notify_lock);
11091108

11101109
/*
11111110
* This is where we wait for a reply from userspace.
11121111
*/
1113-
wait:
1114-
err = wait_for_completion_interruptible(&n.ready);
1115-
mutex_lock(&match->notify_lock);
1116-
if (err == 0) {
1117-
/* Check if we were woken up by a addfd message */
1112+
do {
1113+
mutex_unlock(&match->notify_lock);
1114+
err = wait_for_completion_interruptible(&n.ready);
1115+
mutex_lock(&match->notify_lock);
1116+
if (err != 0)
1117+
goto interrupted;
1118+
11181119
addfd = list_first_entry_or_null(&n.addfd,
11191120
struct seccomp_kaddfd, list);
1120-
if (addfd && n.state != SECCOMP_NOTIFY_REPLIED) {
1121+
/* Check if we were woken up by a addfd message */
1122+
if (addfd)
11211123
seccomp_handle_addfd(addfd);
1122-
mutex_unlock(&match->notify_lock);
1123-
goto wait;
1124-
}
1125-
ret = n.val;
1126-
err = n.error;
1127-
flags = n.flags;
1128-
}
11291124

1125+
} while (n.state != SECCOMP_NOTIFY_REPLIED);
1126+
1127+
ret = n.val;
1128+
err = n.error;
1129+
flags = n.flags;
1130+
1131+
interrupted:
11301132
/* If there were any pending addfd calls, clear them out */
11311133
list_for_each_entry_safe(addfd, tmp, &n.addfd, list) {
11321134
/* The process went away before we got a chance to handle it */

0 commit comments

Comments
 (0)