[Devel] [PATCH RHEL7 COMMIT] ve/seccomp, ptrace: Save original BPF program when setting the filer
Konstantin Khorenko
khorenko at virtuozzo.com
Thu Dec 8 05:30:03 PST 2016
The commit is pushed to "branch-rh7-3.10.0-327.36.1.vz7.20.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-327.36.1.vz7.20.12
------>
commit 185e8e4a2979bd98a935095fc19bdfefcabc78a5
Author: Cyrill Gorcunov <gorcunov at virtuozzo.com>
Date: Thu Dec 8 17:30:03 2016 +0400
ve/seccomp, ptrace: Save original BPF program when setting the filer
The vanilla kernel is quite reworked in filter management, in particular
the filters passed into sockets or seccomp are saved in the userspace form
as struct bpf_prog::orig_prog. We can't port all the patches right now,
lets rather do a trick for seccomp sake and simply carry a copy inside
struct seccomp_filter. The socket filters are decoded into userspace form
anyway so this area is safe.
https://jira.sw.ru/browse/PSBM-55593
CC: Andrey Vagin <avagin at openvz.org>
Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
kernel/seccomp.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index b5f6d50..2d0927b 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -54,6 +54,9 @@
struct seccomp_filter {
atomic_t usage;
struct seccomp_filter *prev;
+#if CONFIG_VE
+ struct sock_fprog orig_prog;
+#endif
unsigned short len; /* Instruction count */
struct sock_filter insns[];
};
@@ -265,6 +268,16 @@ static long seccomp_attach_filter(struct sock_fprog *fprog)
if (copy_from_user(filter->insns, fprog->filter, fp_size))
goto fail;
+#if CONFIG_VE
+ filter->orig_prog.len = fprog->len;
+ filter->orig_prog.filter = kmemdup(filter->insns, fp_size,
+ GFP_KERNEL|__GFP_NOWARN);
+ if (!filter->orig_prog.filter) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+#endif
+
/* Check and rewrite the fprog via the skb checker */
ret = sk_chk_filter(filter->insns, filter->len);
if (ret)
@@ -283,6 +296,9 @@ static long seccomp_attach_filter(struct sock_fprog *fprog)
current->seccomp.filter = filter;
return 0;
fail:
+#if CONFIG_VE
+ kfree(filter->orig_prog.filter);
+#endif
kfree(filter);
return ret;
}
@@ -332,6 +348,9 @@ void put_seccomp_filter(struct task_struct *tsk)
while (orig && atomic_dec_and_test(&orig->usage)) {
struct seccomp_filter *freeme = orig;
orig = orig->prev;
+#if CONFIG_VE
+ kfree(freeme->orig_prog.filter);
+#endif
kfree(freeme);
}
}
@@ -566,8 +585,14 @@ long seccomp_get_filter(struct task_struct *task, unsigned long filter_off,
get_seccomp_filter(task);
spin_unlock_irq(&task->sighand->siglock);
+#if CONFIG_VE
+ if (copy_to_user(data, filter->orig_prog.filter,
+ filter->orig_prog.len * sizeof(filter->orig_prog.filter[0])))
+ ret = -EFAULT;
+#else
if (copy_to_user(data, filter->insns, filter->len * sizeof(filter->insns[0])))
ret = -EFAULT;
+#endif
put_seccomp_filter(task);
return ret;
More information about the Devel
mailing list