Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1423171AbbD2NiF (ORCPT ); Wed, 29 Apr 2015 09:38:05 -0400 Received: from smtp3-g21.free.fr ([212.27.42.3]:37095 "EHLO smtp3-g21.free.fr" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1423043AbbD2NiC (ORCPT ); Wed, 29 Apr 2015 09:38:02 -0400 From: Nicolas Schichan To: Kees Cook , Andy Lutomirski , Will Drewry , linux-kernel@vger.kernel.org Cc: Nicolas Schichan Subject: [PATCH 2/4] seccomp: rework seccomp_prepare_filter(). Date: Wed, 29 Apr 2015 15:37:35 +0200 Message-Id: <1430314657-2552-3-git-send-email-nschichan@freebox.fr> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1430314657-2552-1-git-send-email-nschichan@freebox.fr> References: <1430314657-2552-1-git-send-email-nschichan@freebox.fr> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3135 Lines: 111 - 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 --- 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 majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/