aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/seccomp.c
diff options
context:
space:
mode:
authorTycho Andersen <tycho@tycho.ws>2019-01-12 11:24:20 -0700
committerJames Morris <james.morris@microsoft.com>2019-01-15 09:43:12 -0800
commita811dc61559e0c8003f1086c2a4dc8e4d5ae4cb8 (patch)
tree56144b909f723d0bf4365c2ccbd8ec2e24d9907d /kernel/seccomp.c
parentMerge tag 'trace-v5.0-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace (diff)
downloadlinux-dev-a811dc61559e0c8003f1086c2a4dc8e4d5ae4cb8.tar.xz
linux-dev-a811dc61559e0c8003f1086c2a4dc8e4d5ae4cb8.zip
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: 6a21cc50f0c7 ("seccomp: add a return code to trap to userspace") Signed-off-by: Tycho Andersen <tycho@tycho.ws> Acked-by: Kees Cook <keescook@chromium.org> Signed-off-by: James Morris <james.morris@microsoft.com>
Diffstat (limited to 'kernel/seccomp.c')
-rw-r--r--kernel/seccomp.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index d7f538847b84..e815781ed751 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -976,6 +976,9 @@ static int seccomp_notify_release(struct inode *inode, struct file *file)
struct seccomp_filter *filter = file->private_data;
struct seccomp_knotif *knotif;
+ if (!filter)
+ return 0;
+
mutex_lock(&filter->notify_lock);
/*
@@ -1300,6 +1303,7 @@ out:
out_put_fd:
if (flags & SECCOMP_FILTER_FLAG_NEW_LISTENER) {
if (ret < 0) {
+ listener_f->private_data = NULL;
fput(listener_f);
put_unused_fd(listener);
} else {