Messages in this thread Patch in this message | | | From | Nicolas Schichan <> | Subject | [PATCH 2/4] seccomp: rework seccomp_prepare_filter(). | Date | Wed, 29 Apr 2015 15:37:35 +0200 |
| |
- 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 <nschichan@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
| |