[PATCH] use exactly one seccomp file per filter object

From: Tycho Andersen
Date: Wed Sep 30 2015 - 16:53:48 EST


Signed-off-by: Tycho Andersen <tycho.andersen@xxxxxxxxxxxxx>
---
kernel/seccomp.c | 37 ++++++++++++++++++++++++++++++++-----
1 file changed, 32 insertions(+), 5 deletions(-)

diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index af58c49..ff3b1bd 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -60,6 +60,13 @@ struct seccomp_filter {
atomic_t usage;
struct seccomp_filter *prev;
struct bpf_prog *prog;
+
+ /* The file representing this seccomp_filter, if there is one. A 1:1
+ * file:seccomp_filter mapping allows us to compare seccomp_filters via
+ * kcmp(KCMP_FILE, ...).
+ */
+ struct file *seccomp_file;
+ struct mutex file_lock;
};

/* Limit any path through the tree to 256KB worth of instructions. */
@@ -395,6 +402,7 @@ static struct seccomp_filter *seccomp_prepare_filter(struct sock_fprog *fprog)
}

atomic_set(&sfilter->usage, 1);
+ mutex_init(&sfilter->file_lock);

return sfilter;
}
@@ -821,7 +829,14 @@ out_free:

int seccomp_fd_release(struct inode *ino, struct file *f)
{
- seccomp_filter_decref(f->private_data);
+ struct seccomp_filter *filter = f->private_data;
+
+ mutex_lock(&filter->file_lock);
+ filter->seccomp_file = NULL;
+ mutex_unlock(&filter->file_lock);
+
+ seccomp_filter_decref(filter);
+
return 0;
}

@@ -1073,7 +1088,9 @@ long prctl_set_seccomp(unsigned long seccomp_mode, char __user *filter)
long seccomp_get_filter_fd(struct task_struct *task, long n)
{
struct seccomp_filter *filter;
+ struct file *file;
long fd;
+ int flags = O_RDONLY | O_CLOEXEC;

if (task->seccomp.mode != SECCOMP_MODE_FILTER)
return -EINVAL;
@@ -1087,11 +1104,21 @@ long seccomp_get_filter_fd(struct task_struct *task, long n)
if (!filter)
return -EINVAL;

- atomic_inc(&filter->usage);
- fd = anon_inode_getfd("seccomp", &seccomp_fops, filter,
- O_RDONLY | O_CLOEXEC);
+ fd = get_unused_fd_flags(flags);
if (fd < 0)
- seccomp_filter_decref(filter);
+ return fd;
+
+ mutex_lock(&filter->file_lock);
+ file = filter->seccomp_file;
+ if (!file) {
+ atomic_inc(&filter->usage);
+ file = anon_inode_getfile("seccomp", &seccomp_fops, filter,
+ flags);
+ filter->seccomp_file = file;
+ }
+ mutex_unlock(&filter->file_lock);
+
+ fd_install(fd, file);

return fd;
}
--
2.5.0


--2fHTh5uZTiUOsy+g--
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/