- Try to use the classic BPF JIT via bpf_jit_compile().

- Use bpf_migrate_filter() from NET filter code instead of the double
  bpf_convert_filter() followed by bpf_prog_select_runtime() if
  classic bpf_jit_compile() did not succeed in producing native code.

Signed-off-by: Nicolas Schichan <nschic...@freebox.fr>
---
 kernel/seccomp.c | 47 ++++++++++++++++++++---------------------------
 1 file changed, 20 insertions(+), 27 deletions(-)

diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index 4f44028..4f9fea7 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -348,8 +348,7 @@ static struct seccomp_filter *seccomp_prepare_filter(struct 
sock_fprog *fprog)
 {
        struct seccomp_filter *filter;
        unsigned long fp_size;
-       struct sock_filter *fp;
-       int new_len;
+       struct bpf_prog *fp;
        long ret;
 
        if (fprog->len == 0 || fprog->len > BPF_MAXINSNS)
@@ -368,29 +367,38 @@ static struct seccomp_filter 
*seccomp_prepare_filter(struct sock_fprog *fprog)
                                     CAP_SYS_ADMIN) != 0)
                return ERR_PTR(-EACCES);
 
-       fp = kzalloc(fp_size, GFP_KERNEL|__GFP_NOWARN);
+       fp = bpf_prog_alloc(bpf_prog_size(fprog->len), __GFP_NOWARN);
        if (!fp)
                return ERR_PTR(-ENOMEM);
 
        /* Copy the instructions from fprog. */
        ret = -EFAULT;
-       if (copy_from_user(fp, fprog->filter, fp_size))
+       if (copy_from_user(fp->insns, fprog->filter, fp_size))
                goto free_prog;
+       fp->len = fprog->len;
 
        /* Check and rewrite the fprog via the skb checker */
-       ret = bpf_check_classic(fp, fprog->len);
+       ret = bpf_check_classic(fp->insns, fp->len);
        if (ret)
                goto free_prog;
 
        /* Check and rewrite the fprog for seccomp use */
-       ret = seccomp_check_filter(fp, fprog->len);
+       ret = seccomp_check_filter(fp->insns, fp->len);
        if (ret)
                goto free_prog;
 
-       /* Convert 'sock_filter' insns to 'bpf_insn' insns */
-       ret = bpf_convert_filter(fp, fprog->len, NULL, &new_len);
-       if (ret)
-               goto free_prog;
+       /* try to use the classic JIT */
+       bpf_jit_compile(fp);
+
+       if (!fp->jited) {
+               /*
+                * if classic JIT has failed, try to convert it to an
+                * internal filter
+                */
+               fp = bpf_migrate_filter(fp);
+               if (IS_ERR(fp))
+                       return fp;
+       }
 
        /* Allocate a new seccomp_filter */
        ret = -ENOMEM;
@@ -399,28 +407,13 @@ static struct seccomp_filter 
*seccomp_prepare_filter(struct sock_fprog *fprog)
        if (!filter)
                goto free_prog;
 
-       filter->prog = bpf_prog_alloc(bpf_prog_size(new_len), __GFP_NOWARN);
-       if (!filter->prog)
-               goto free_filter;
-
-       ret = bpf_convert_filter(fp, fprog->len, filter->prog->insnsi, 
&new_len);
-       if (ret)
-               goto free_filter_prog;
-
-       kfree(fp);
+       filter->prog = fp;
        atomic_set(&filter->usage, 1);
-       filter->prog->len = new_len;
-
-       bpf_prog_select_runtime(filter->prog);
 
        return filter;
 
-free_filter_prog:
-       __bpf_prog_free(filter->prog);
-free_filter:
-       kfree(filter);
 free_prog:
-       kfree(fp);
+       bpf_prog_destroy(fp);
        return ERR_PTR(ret);
 }
 
-- 
1.9.1

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

Reply via email to