Commit a811dc61 authored by Tycho Andersen's avatar Tycho Andersen Committed by James Morris

seccomp: fix UAF in user-trap code

On the failure path, we do an fput() of the listener fd if the filter fails
to install (e.g. because of a TSYNC race that's lost, or if the thread is
killed, etc.). fput() doesn't actually release the fd, it just ads it to a
work queue. Then the thread proceeds to free the filter, even though the
listener struct file has a reference to it.

To fix this, on the failure path let's set the private data to null, so we
know in ->release() to ignore the filter.

Reported-by: syzbot+981c26489b2d1c6316ba@syzkaller.appspotmail.com
Fixes: 6a21cc50 ("seccomp: add a return code to trap to userspace")
Signed-off-by: default avatarTycho Andersen <tycho@tycho.ws>
Acked-by: default avatarKees Cook <keescook@chromium.org>
Signed-off-by: default avatarJames Morris <james.morris@microsoft.com>
parent 7939f8be
...@@ -976,6 +976,9 @@ static int seccomp_notify_release(struct inode *inode, struct file *file) ...@@ -976,6 +976,9 @@ static int seccomp_notify_release(struct inode *inode, struct file *file)
struct seccomp_filter *filter = file->private_data; struct seccomp_filter *filter = file->private_data;
struct seccomp_knotif *knotif; struct seccomp_knotif *knotif;
if (!filter)
return 0;
mutex_lock(&filter->notify_lock); mutex_lock(&filter->notify_lock);
/* /*
...@@ -1300,6 +1303,7 @@ static long seccomp_set_mode_filter(unsigned int flags, ...@@ -1300,6 +1303,7 @@ static long seccomp_set_mode_filter(unsigned int flags,
out_put_fd: out_put_fd:
if (flags & SECCOMP_FILTER_FLAG_NEW_LISTENER) { if (flags & SECCOMP_FILTER_FLAG_NEW_LISTENER) {
if (ret < 0) { if (ret < 0) {
listener_f->private_data = NULL;
fput(listener_f); fput(listener_f);
put_unused_fd(listener); put_unused_fd(listener);
} else { } else {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment