BPF updates
Subsystems (6)
Daniel Borkmann
maintainercover BPF updates
This set gets rid of BPF special handling in seccomp filter preparation and provides generic infrastructure from BPF side, which eventually also allows for classic BPF JITs to add support for seccomp filters.
Daniel Borkmann (2):
net: filter: add __GFP_NOWARN flag for larger kmem allocs seccomp, filter: add and use bpf_prog_create_from_user from seccomp
Nicolas Schichan (2):
net: filter: add a callback to allow classic post-verifier transformations
seccomp: simplify seccomp_prepare_filter and reuse bpf_prepare_filter
include/linux/filter.h | 10 +++--- kernel/seccomp.c | 70 +++++++++--------------------------------- net/core/filter.c | 82 ++++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 91 insertions(+), 71 deletions(-)
Signature · 1 line
1.9.3
Daniel Borkmann
maintainerPATCH 1/4 net: filter: add a callback to allow classic post-verifier transformations
From: Nicolas Schichan <[email protected]>
This is in preparation for use by the seccomp code, the rationale is not to duplicate additional code within the seccomp layer, but instead, have it abstracted and hidden within the classic BPF API.
As an interim step, this now also makes bpf_prepare_filter() visible (not as exported symbol though), so that seccomp can reuse that code path instead of reimplementing it.
Joint work with Daniel Borkmann.
--- include/linux/filter.h | 6 ++++++ net/core/filter.c | 18 +++++++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-)
include/linux/filter.h +6 -0
@@ -384,7 +384,13 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk);int sk_attach_bpf (u32 ufd,struct sock *sk);int sk_detach_filter (struct sock *sk); +typedef int (*bpf_aux_classic_check_t )(struct sock_filter *filter, +unsigned int flen); +int bpf_check_classic (const struct sock_filter *filter,unsigned int flen); +struct bpf_prog *bpf_prepare_filter (struct bpf_prog *fp, +bpf_aux_classic_check_t trans); +int sk_get_filter (struct sock *sk,struct sock_filter __user *filter,unsigned int len);
net/core/filter.c +15 -3
@@ -988,7 +988,8 @@ out_err:return ERR_PTR (err); } -static struct bpf_prog *bpf_prepare_filter (struct bpf_prog *fp) +struct bpf_prog *bpf_prepare_filter (struct bpf_prog *fp, +bpf_aux_classic_check_t trans) {int err;
@@ -1001,6 +1002,17 @@ static struct bpf_prog *bpf_prepare_filter(struct bpf_prog *fp)return ERR_PTR (err); } +/* There might be additional checks and transformations +* needed on classic filters, f.e. in case of seccomp. +*/ +if (trans) { + err =trans (fp->insns, fp->len); +if (err) { +__bpf_prog_release (fp); +return ERR_PTR (err); + } + } +/* Probe if we can JIT compile the filter and if so, do * the compilation of the filter. */
@@ -1050,7 +1062,7 @@ int bpf_prog_create(struct bpf_prog **pfp, struct sock_fprog_kern *fprog)/* bpf_prepare_filter() already takes care of freeing * memory in case something goes wrong. */ - fp =bpf_prepare_filter (fp); + fp =bpf_prepare_filter (fp,NULL );if (IS_ERR (fp))return PTR_ERR (fp);
@@ -1135,7 +1147,7 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)/* bpf_prepare_filter() already takes care of freeing * memory in case something goes wrong. */ - prog =bpf_prepare_filter (prog); + prog =bpf_prepare_filter (prog,NULL );if (IS_ERR (prog))return PTR_ERR (prog);
Signature · 1 line
1.9.3
Daniel Borkmann
maintainerPATCH 2/4 seccomp: simplify seccomp_prepare_filter and reuse bpf_prepare_filter
In reply to Daniel BorkmannFrom: Nicolas Schichan <[email protected]>
Remove the calls to bpf_check_classic(), bpf_convert_filter() and bpf_migrate_runtime() and let bpf_prepare_filter() take care of that instead.
seccomp_check_filter() is passed to bpf_prepare_filter() so that it gets called from there, after bpf_check_classic().
We can now remove exposure of two internal classic BPF functions previously used by seccomp. The export of bpf_check_classic() symbol, previously known as sk_chk_filter(), was there since pre git times, and no in-tree module was using it, therefore remove it.
Joint work with Daniel Borkmann.
--- include/linux/filter.h | 4 --- kernel/seccomp.c | 68 ++++++++++++++++---------------------------------- net/core/filter.c | 8 +++--- 3 files changed, 26 insertions(+), 54 deletions(-)
include/linux/filter.h +0 -4
@@ -363,9 +363,6 @@ int sk_filter(struct sock *sk, struct sk_buff *skb);void bpf_prog_select_runtime (struct bpf_prog *fp);void bpf_prog_free (struct bpf_prog *fp); -int bpf_convert_filter (struct sock_filter *prog,int len, -struct bpf_insn *new_prog,int *new_len); -struct bpf_prog *bpf_prog_alloc (unsigned int size,gfp_t gfp_extra_flags);struct bpf_prog *bpf_prog_realloc (struct bpf_prog *fp_old,unsigned int size,gfp_t gfp_extra_flags);
@@ -387,7 +384,6 @@ int sk_detach_filter(struct sock *sk);typedef int (*bpf_aux_classic_check_t )(struct sock_filter *filter,unsigned int flen); -int bpf_check_classic (const struct sock_filter *filter,unsigned int flen);struct bpf_prog *bpf_prepare_filter (struct bpf_prog *fp,bpf_aux_classic_check_t trans);
kernel/seccomp.c +22 -46
97 lines not on this page · raw message
net/core/filter.c +4 -4
@@ -355,8 +355,8 @@ static bool convert_bpf_extensions(struct sock_filter *fp,* for socket filters: ctx == 'struct sk_buff *', for seccomp: * ctx == 'struct seccomp_data *'. */ -int bpf_convert_filter (struct sock_filter *prog,int len, -struct bpf_insn *new_prog,int *new_len) +static int bpf_convert_filter (struct sock_filter *prog,int len, +struct bpf_insn *new_prog,int *new_len) {int new_flen =0 , pass =0 , target, i;struct bpf_insn *new_insn;
@@ -751,7 +751,8 @@ static bool chk_code_allowed(u16 code_to_probe)* * Returns 0 if the rule set is legal or -EINVAL if not. */ -int bpf_check_classic (const struct sock_filter *filter,unsigned int flen) +static int bpf_check_classic (const struct sock_filter *filter, +unsigned int flen) {bool anc_found;int pc;
@@ -825,7 +826,6 @@ int bpf_check_classic(const struct sock_filter *filter, unsigned int flen)return -EINVAL ; } -EXPORT_SYMBOL (bpf_check_classic);static int bpf_prog_store_orig_filter (struct bpf_prog *fp,const struct sock_fprog *fprog)
Signature · 1 line
1.9.3
Daniel Borkmann
maintainerPATCH 4/4 seccomp, filter: add and use bpf_prog_create_from_user from seccomp
In reply to Daniel BorkmannSeccomp has always been a special candidate when it comes to preparation of its filters in seccomp_prepare_filter(). Due to the extra checks and filter rewrite it partially duplicates code and has BPF internals exposed.
This patch adds a generic API inside the BPF code code that seccomp can use and thus keep it's filter preparation code minimal and better maintainable. The other side-effect is that now classic JITs can add seccomp support as well by only providing a BPF_LDX | BPF_W | BPF_ABS translation.
Tested with seccomp and BPF test suites.
--- include/linux/filter.h | 12 +++++------- kernel/seccomp.c | 42 ++++++++++++----------------------------- net/core/filter.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 66 insertions(+), 39 deletions(-)
include/linux/filter.h +5 -7
@@ -374,19 +374,17 @@ static inline void bpf_prog_unlock_free(struct bpf_prog *fp)__bpf_prog_free (fp); } +typedef int (*bpf_aux_classic_check_t )(struct sock_filter *filter, +unsigned int flen); +int bpf_prog_create (struct bpf_prog **pfp,struct sock_fprog_kern *fprog); +int bpf_prog_create_from_user (struct bpf_prog **pfp,struct sock_fprog *fprog, +bpf_aux_classic_check_t trans);void bpf_prog_destroy (struct bpf_prog *fp);int sk_attach_filter (struct sock_fprog *fprog,struct sock *sk);int sk_attach_bpf (u32 ufd,struct sock *sk);int sk_detach_filter (struct sock *sk); - -typedef int (*bpf_aux_classic_check_t )(struct sock_filter *filter, -unsigned int flen); - -struct bpf_prog *bpf_prepare_filter (struct bpf_prog *fp, -bpf_aux_classic_check_t trans); -int sk_get_filter (struct sock *sk,struct sock_filter __user *filter,unsigned int len);
kernel/seccomp.c +12 -30
64 lines not on this page · raw message
net/core/filter.c +49 -2
63 lines not on this page · raw message
Signature · 1 line
1.9.3
Daniel Borkmann
maintainerPATCH 3/4 net: filter: add __GFP_NOWARN flag for larger kmem allocs
In reply to Daniel BorkmannWhen seccomp BPF was added, it was discussed to add __GFP_NOWARN flag for their configuration path as f.e. up to 32K allocations are more prone to fail under stress. As we're going to reuse BPF API, add __GFP_NOWARN flags where larger kmalloc() and friends allocations could fail.
It doesn't make much sense to pass around __GFP_NOWARN everywhere as an extra argument only for seccomp while we just as well could run into similar issues for socket filters, where it's not desired to have a user application throw a WARN() due to allocation failure.
--- net/core/filter.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
net/core/filter.c +6 -3
@@ -371,7 +371,8 @@ static int bpf_convert_filter(struct sock_filter *prog, int len,return -EINVAL ;if (new_prog) { - addrs =kcalloc (len,sizeof (*addrs),GFP_KERNEL ); + addrs =kcalloc (len,sizeof (*addrs), +GFP_KERNEL | __GFP_NOWARN);if (!addrs)return -ENOMEM ; }
@@ -839,7 +840,9 @@ static int bpf_prog_store_orig_filter(struct bpf_prog *fp, fkprog = fp->orig_prog; fkprog->len = fprog->len; - fkprog->filter =kmemdup (fp->insns, fsize,GFP_KERNEL ); + + fkprog->filter =kmemdup (fp->insns, fsize, +GFP_KERNEL | __GFP_NOWARN);if (!fkprog->filter) {kfree (fp->orig_prog);return -ENOMEM ;
@@ -941,7 +944,7 @@ static struct bpf_prog *bpf_migrate_filter(struct bpf_prog *fp)* pass. At this time, the user BPF is stored in fp->insns. */ old_prog =kmemdup (fp->insns, old_len *sizeof (struct sock_filter ), -GFP_KERNEL ); +GFP_KERNEL | __GFP_NOWARN);if (!old_prog) { err = -ENOMEM ; goto out_err;
Signature · 1 line
1.9.3
Re: [PATCH net-next 1/4] net: filter: add a callback to allow classic post-verifier transformations
In reply to Daniel BorkmannQuoted 10 lines · Daniel Borkmann
From: Nicolas Schichan <[email protected]>
This is in preparation for use by the seccomp code, the rationale is not to duplicate additional code within the seccomp layer, but instead, have it abstracted and hidden within the classic BPF API.
As an interim step, this now also makes
bpf_prepare_filter()visible (not as exported symbol though), so that seccomp can reuse that code path instead of reimplementing it.
Quoted 6 lines
Joint work with Daniel Borkmann.
Signed-off-by Nicolas Schichan <[email protected]>Signed-off-by Daniel Borkmann <[email protected]>Cc Alexei Starovoitov <[email protected]>Cc Kees Cook <[email protected]>
Re: [PATCH net-next 2/4] seccomp: simplify seccomp_prepare_filter and reuse bpf_prepare_filter
In reply to Daniel BorkmannQuoted 14 lines · Daniel Borkmann
From: Nicolas Schichan <[email protected]>
Remove the calls to
bpf_check_classic(),bpf_convert_filter()andbpf_migrate_runtime()and letbpf_prepare_filter()take care of that instead.
seccomp_check_filter()is passed tobpf_prepare_filter()so that it gets called from there, afterbpf_check_classic().We can now remove exposure of two internal classic BPF functions previously used by seccomp. The export of
bpf_check_classic()symbol, previously known assk_chk_filter(), was there since pre git times, and no in-tree module was using it, therefore remove it.
Quoted 6 lines
Joint work with Daniel Borkmann.
Signed-off-by Nicolas Schichan <[email protected]>Signed-off-by Daniel Borkmann <[email protected]>Cc Alexei Starovoitov <[email protected]>Cc Kees Cook <[email protected]>
Re: [PATCH net-next 3/4] net: filter: add __GFP_NOWARN flag for larger kmem allocs
In reply to Daniel BorkmannQuoted 11 lines · Daniel Borkmann
When seccomp BPF was added, it was discussed to add
__GFP_NOWARNflag for their configuration path as f.e. up to 32K allocations are more prone to fail under stress. As we're going to reuse BPF API, add__GFP_NOWARNflags where largerkmalloc()and friends allocations could fail.It doesn't make much sense to pass around
__GFP_NOWARNeverywhere as an extra argument only for seccomp while we just as well could run into similar issues for socket filters, where it's not desired to have a user application throw aWARN()due to allocation failure.
Quoted 4 lines
Signed-off-by Daniel Borkmann <[email protected]>Cc Nicolas Schichan <[email protected]>Cc Alexei Starovoitov <[email protected]>Cc Kees Cook <[email protected]>
Re: [PATCH net-next 4/4] seccomp, filter: add and use bpf_prog_create_from_user from seccomp
In reply to Daniel BorkmannQuoted 9 lines · Daniel Borkmann
Seccomp has always been a special candidate when it comes to preparation of its filters in
seccomp_prepare_filter(). Due to the extra checks and filter rewrite it partially duplicates code and has BPF internals exposed.This patch adds a generic API inside the BPF code code that seccomp can use and thus keep it's filter preparation code minimal and better maintainable. The other side-effect is that now classic JITs can add seccomp support as well by only providing a
BPF_LDX|BPF_W|BPF_ABStranslation.
Quoted 6 lines
Tested with seccomp and BPF test suites.
Signed-off-by Daniel Borkmann <[email protected]>Cc Nicolas Schichan <[email protected]>Cc Alexei Starovoitov <[email protected]>Cc Kees Cook <[email protected]>
David Miller
maintainerFrom: Daniel Borkmann <[email protected]>
Date: Wed, 6 May 2015 16:12:26 +0200
Quoted 3 lines
This set gets rid of BPF special handling in seccomp filter preparation and provides generic infrastructure from BPF side, which eventually also allows for classic BPF JITs to add support for seccomp filters.
I'll apply this series, thanks.