* [PATCH v4 net-next 0/5] net: filter: split sk_filter into socket and bpf, cleanup names
@ 2014-07-31 3:34 Alexei Starovoitov
2014-07-31 3:34 ` [PATCH v4 net-next 1/5] net: filter: simplify socket charging Alexei Starovoitov
` (5 more replies)
0 siblings, 6 replies; 14+ messages in thread
From: Alexei Starovoitov @ 2014-07-31 3:34 UTC (permalink / raw)
To: David S. Miller
Cc: Daniel Borkmann, Willem de Bruijn, Pablo Neira Ayuso, Kees Cook,
netdev, linux-kernel, netfilter-devel
The main goal of the series is to split 'struct sk_filter' into socket and
bpf parts and cleanup names in the following way:
- everything that deals with sockets keeps 'sk_*' prefix
- everything that is pure BPF is changed to 'bpf_*' prefix
split 'struct sk_filter' into
struct sk_filter {
atomic_t refcnt;
struct rcu_head rcu;
struct bpf_prog *prog;
};
and
struct bpf_prog {
u32 jited:1,
len:31;
struct sock_fprog_kern *orig_prog;
unsigned int (*bpf_func)(const struct sk_buff *skb,
const struct bpf_insn *filter);
union {
struct sock_filter insns[0];
struct bpf_insn insnsi[0];
struct work_struct work;
};
};
so that 'struct bpf_prog' can be used independent of sockets and cleans up
'unattached' bpf use cases:
isdn, ppp, team, seccomp, ptp, xt_bpf, cls_bpf, test_bpf
which don't need refcnt/rcu fields.
It's a follow up to the rcu cleanup started by Pablo in
commit 34c5bd66e5 ("net: filter: don't release unattached filter through call_rcu()")
Patch 1 - cleans up socket memory charging and makes it possible for functions
sk(bpf)_migrate_filter(), sk(bpf)_prepare_filter() to be socket independent
Patches 2-4 - trivial renames
Patch 5 - sk_filter split and renames of related sk_*() functions
Alexei Starovoitov (5):
net: filter: simplify socket charging
net: filter: rename sk_filter_proglen -> bpf_classic_proglen
net: filter: rename sk_chk_filter() -> bpf_check_classic()
net: filter: rename sk_convert_filter() -> bpf_convert_filter()
net: filter: split 'struct sk_filter' into socket and bpf parts
Documentation/networking/filter.txt | 12 +-
arch/arm/net/bpf_jit_32.c | 8 +-
arch/mips/net/bpf_jit.c | 8 +-
arch/powerpc/net/bpf_jit_comp.c | 8 +-
arch/s390/net/bpf_jit_comp.c | 4 +-
arch/sparc/net/bpf_jit_comp.c | 4 +-
arch/x86/net/bpf_jit_comp.c | 14 +--
drivers/isdn/i4l/isdn_ppp.c | 26 ++---
drivers/net/ppp/ppp_generic.c | 28 ++---
drivers/net/team/team_mode_loadbalance.c | 14 +--
include/linux/filter.h | 51 +++++----
include/linux/isdn_ppp.h | 4 +-
include/uapi/linux/netfilter/xt_bpf.h | 4 +-
kernel/bpf/core.c | 34 +++---
kernel/seccomp.c | 18 +--
lib/test_bpf.c | 24 ++--
net/core/filter.c | 183 +++++++++++++++---------------
net/core/ptp_classifier.c | 6 +-
net/core/sock.c | 9 +-
net/core/sock_diag.c | 4 +-
net/netfilter/xt_bpf.c | 6 +-
net/sched/cls_bpf.c | 12 +-
22 files changed, 243 insertions(+), 238 deletions(-)
--
1.7.9.5
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v4 net-next 1/5] net: filter: simplify socket charging
2014-07-31 3:34 [PATCH v4 net-next 0/5] net: filter: split sk_filter into socket and bpf, cleanup names Alexei Starovoitov
@ 2014-07-31 3:34 ` Alexei Starovoitov
2014-07-31 3:34 ` [PATCH v4 net-next 2/5] net: filter: rename sk_filter_proglen -> bpf_classic_proglen Alexei Starovoitov
` (4 subsequent siblings)
5 siblings, 0 replies; 14+ messages in thread
From: Alexei Starovoitov @ 2014-07-31 3:34 UTC (permalink / raw)
To: David S. Miller
Cc: Daniel Borkmann, Willem de Bruijn, Pablo Neira Ayuso, Kees Cook,
netdev, linux-kernel, netfilter-devel
attaching bpf program to a socket involves multiple socket memory arithmetic,
since size of 'sk_filter' is changing when classic BPF is converted to eBPF.
Also common path of program creation has to deal with two ways of freeing
the memory.
Simplify the code by delaying socket charging until program is ready and
its size is known
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
---
include/linux/filter.h | 2 +-
net/core/filter.c | 87 ++++++++++++++++++++----------------------------
net/core/sock.c | 9 +++--
3 files changed, 45 insertions(+), 53 deletions(-)
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 20dd50ef7271..00640edc166f 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -366,7 +366,7 @@ int sk_chk_filter(const struct sock_filter *filter, unsigned int flen);
int sk_get_filter(struct sock *sk, struct sock_filter __user *filter,
unsigned int len);
-void sk_filter_charge(struct sock *sk, struct sk_filter *fp);
+bool sk_filter_charge(struct sock *sk, struct sk_filter *fp);
void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp);
u64 __bpf_call_base(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5);
diff --git a/net/core/filter.c b/net/core/filter.c
index 42c1944b0c63..5a6aeb1d40b8 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -872,41 +872,30 @@ static void sk_filter_release(struct sk_filter *fp)
void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp)
{
- atomic_sub(sk_filter_size(fp->len), &sk->sk_omem_alloc);
- sk_filter_release(fp);
-}
+ u32 filter_size = sk_filter_size(fp->len);
-void sk_filter_charge(struct sock *sk, struct sk_filter *fp)
-{
- atomic_inc(&fp->refcnt);
- atomic_add(sk_filter_size(fp->len), &sk->sk_omem_alloc);
+ atomic_sub(filter_size, &sk->sk_omem_alloc);
+ sk_filter_release(fp);
}
-static struct sk_filter *__sk_migrate_realloc(struct sk_filter *fp,
- struct sock *sk,
- unsigned int len)
+/* try to charge the socket memory if there is space available
+ * return true on success
+ */
+bool sk_filter_charge(struct sock *sk, struct sk_filter *fp)
{
- struct sk_filter *fp_new;
-
- if (sk == NULL)
- return krealloc(fp, len, GFP_KERNEL);
-
- fp_new = sock_kmalloc(sk, len, GFP_KERNEL);
- if (fp_new) {
- *fp_new = *fp;
- /* As we're keeping orig_prog in fp_new along,
- * we need to make sure we're not evicting it
- * from the old fp.
- */
- fp->orig_prog = NULL;
- sk_filter_uncharge(sk, fp);
+ u32 filter_size = sk_filter_size(fp->len);
+
+ /* same check as in sock_kmalloc() */
+ if (filter_size <= sysctl_optmem_max &&
+ atomic_read(&sk->sk_omem_alloc) + filter_size < sysctl_optmem_max) {
+ atomic_inc(&fp->refcnt);
+ atomic_add(filter_size, &sk->sk_omem_alloc);
+ return true;
}
-
- return fp_new;
+ return false;
}
-static struct sk_filter *__sk_migrate_filter(struct sk_filter *fp,
- struct sock *sk)
+static struct sk_filter *__sk_migrate_filter(struct sk_filter *fp)
{
struct sock_filter *old_prog;
struct sk_filter *old_fp;
@@ -938,7 +927,7 @@ static struct sk_filter *__sk_migrate_filter(struct sk_filter *fp,
/* Expand fp for appending the new filter representation. */
old_fp = fp;
- fp = __sk_migrate_realloc(old_fp, sk, sk_filter_size(new_len));
+ fp = krealloc(old_fp, sk_filter_size(new_len), GFP_KERNEL);
if (!fp) {
/* The old_fp is still around in case we couldn't
* allocate new memory, so uncharge on that one.
@@ -956,7 +945,7 @@ static struct sk_filter *__sk_migrate_filter(struct sk_filter *fp,
/* 2nd sk_convert_filter() can fail only if it fails
* to allocate memory, remapping must succeed. Note,
* that at this time old_fp has already been released
- * by __sk_migrate_realloc().
+ * by krealloc().
*/
goto out_err_free;
@@ -968,16 +957,11 @@ static struct sk_filter *__sk_migrate_filter(struct sk_filter *fp,
out_err_free:
kfree(old_prog);
out_err:
- /* Rollback filter setup. */
- if (sk != NULL)
- sk_filter_uncharge(sk, fp);
- else
- kfree(fp);
+ __sk_filter_release(fp);
return ERR_PTR(err);
}
-static struct sk_filter *__sk_prepare_filter(struct sk_filter *fp,
- struct sock *sk)
+static struct sk_filter *__sk_prepare_filter(struct sk_filter *fp)
{
int err;
@@ -986,10 +970,7 @@ static struct sk_filter *__sk_prepare_filter(struct sk_filter *fp,
err = sk_chk_filter(fp->insns, fp->len);
if (err) {
- if (sk != NULL)
- sk_filter_uncharge(sk, fp);
- else
- kfree(fp);
+ __sk_filter_release(fp);
return ERR_PTR(err);
}
@@ -1002,7 +983,7 @@ static struct sk_filter *__sk_prepare_filter(struct sk_filter *fp,
* internal BPF translation for the optimized interpreter.
*/
if (!fp->jited)
- fp = __sk_migrate_filter(fp, sk);
+ fp = __sk_migrate_filter(fp);
return fp;
}
@@ -1041,10 +1022,10 @@ int sk_unattached_filter_create(struct sk_filter **pfp,
*/
fp->orig_prog = NULL;
- /* __sk_prepare_filter() already takes care of uncharging
+ /* __sk_prepare_filter() already takes care of freeing
* memory in case something goes wrong.
*/
- fp = __sk_prepare_filter(fp, NULL);
+ fp = __sk_prepare_filter(fp);
if (IS_ERR(fp))
return PTR_ERR(fp);
@@ -1083,31 +1064,37 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
if (fprog->filter == NULL)
return -EINVAL;
- fp = sock_kmalloc(sk, sk_fsize, GFP_KERNEL);
+ fp = kmalloc(sk_fsize, GFP_KERNEL);
if (!fp)
return -ENOMEM;
if (copy_from_user(fp->insns, fprog->filter, fsize)) {
- sock_kfree_s(sk, fp, sk_fsize);
+ kfree(fp);
return -EFAULT;
}
- atomic_set(&fp->refcnt, 1);
fp->len = fprog->len;
err = sk_store_orig_filter(fp, fprog);
if (err) {
- sk_filter_uncharge(sk, fp);
+ kfree(fp);
return -ENOMEM;
}
- /* __sk_prepare_filter() already takes care of uncharging
+ /* __sk_prepare_filter() already takes care of freeing
* memory in case something goes wrong.
*/
- fp = __sk_prepare_filter(fp, sk);
+ fp = __sk_prepare_filter(fp);
if (IS_ERR(fp))
return PTR_ERR(fp);
+ atomic_set(&fp->refcnt, 0);
+
+ if (!sk_filter_charge(sk, fp)) {
+ __sk_filter_release(fp);
+ return -ENOMEM;
+ }
+
old_fp = rcu_dereference_protected(sk->sk_filter,
sock_owned_by_user(sk));
rcu_assign_pointer(sk->sk_filter, fp);
diff --git a/net/core/sock.c b/net/core/sock.c
index 134291d73fcd..a741163568fa 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1474,6 +1474,7 @@ static void sk_update_clone(const struct sock *sk, struct sock *newsk)
struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
{
struct sock *newsk;
+ bool is_charged = true;
newsk = sk_prot_alloc(sk->sk_prot, priority, sk->sk_family);
if (newsk != NULL) {
@@ -1518,9 +1519,13 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
filter = rcu_dereference_protected(newsk->sk_filter, 1);
if (filter != NULL)
- sk_filter_charge(newsk, filter);
+ /* though it's an empty new sock, the charging may fail
+ * if sysctl_optmem_max was changed between creation of
+ * original socket and cloning
+ */
+ is_charged = sk_filter_charge(newsk, filter);
- if (unlikely(xfrm_sk_clone_policy(newsk))) {
+ if (unlikely(!is_charged || xfrm_sk_clone_policy(newsk))) {
/* It is still raw copy of parent, so invalidate
* destructor and make plain sk_free() */
newsk->sk_destruct = NULL;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v4 net-next 2/5] net: filter: rename sk_filter_proglen -> bpf_classic_proglen
2014-07-31 3:34 [PATCH v4 net-next 0/5] net: filter: split sk_filter into socket and bpf, cleanup names Alexei Starovoitov
2014-07-31 3:34 ` [PATCH v4 net-next 1/5] net: filter: simplify socket charging Alexei Starovoitov
@ 2014-07-31 3:34 ` Alexei Starovoitov
2014-07-31 3:34 ` [PATCH v4 net-next 3/5] net: filter: rename sk_chk_filter() -> bpf_check_classic() Alexei Starovoitov
` (3 subsequent siblings)
5 siblings, 0 replies; 14+ messages in thread
From: Alexei Starovoitov @ 2014-07-31 3:34 UTC (permalink / raw)
To: David S. Miller
Cc: Daniel Borkmann, Willem de Bruijn, Pablo Neira Ayuso, Kees Cook,
netdev, linux-kernel, netfilter-devel
trivial rename to better match semantics of macro
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
---
include/linux/filter.h | 3 +--
net/core/filter.c | 8 ++++----
net/core/sock_diag.c | 2 +-
3 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 00640edc166f..3769341a745d 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -344,8 +344,7 @@ static inline unsigned int sk_filter_size(unsigned int proglen)
offsetof(struct sk_filter, insns[proglen]));
}
-#define sk_filter_proglen(fprog) \
- (fprog->len * sizeof(fprog->filter[0]))
+#define bpf_classic_proglen(fprog) (fprog->len * sizeof(fprog->filter[0]))
int sk_filter(struct sock *sk, struct sk_buff *skb);
diff --git a/net/core/filter.c b/net/core/filter.c
index 5a6aeb1d40b8..d6cb287e4f59 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -813,7 +813,7 @@ EXPORT_SYMBOL(sk_chk_filter);
static int sk_store_orig_filter(struct sk_filter *fp,
const struct sock_fprog *fprog)
{
- unsigned int fsize = sk_filter_proglen(fprog);
+ unsigned int fsize = bpf_classic_proglen(fprog);
struct sock_fprog_kern *fkprog;
fp->orig_prog = kmalloc(sizeof(*fkprog), GFP_KERNEL);
@@ -1001,7 +1001,7 @@ static struct sk_filter *__sk_prepare_filter(struct sk_filter *fp)
int sk_unattached_filter_create(struct sk_filter **pfp,
struct sock_fprog_kern *fprog)
{
- unsigned int fsize = sk_filter_proglen(fprog);
+ unsigned int fsize = bpf_classic_proglen(fprog);
struct sk_filter *fp;
/* Make sure new filter is there and in the right amounts. */
@@ -1053,7 +1053,7 @@ EXPORT_SYMBOL_GPL(sk_unattached_filter_destroy);
int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
{
struct sk_filter *fp, *old_fp;
- unsigned int fsize = sk_filter_proglen(fprog);
+ unsigned int fsize = bpf_classic_proglen(fprog);
unsigned int sk_fsize = sk_filter_size(fprog->len);
int err;
@@ -1154,7 +1154,7 @@ int sk_get_filter(struct sock *sk, struct sock_filter __user *ubuf,
goto out;
ret = -EFAULT;
- if (copy_to_user(ubuf, fprog->filter, sk_filter_proglen(fprog)))
+ if (copy_to_user(ubuf, fprog->filter, bpf_classic_proglen(fprog)))
goto out;
/* Instead of bytes, the API requests to return the number
diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c
index a4216a4c9572..57d922320c59 100644
--- a/net/core/sock_diag.c
+++ b/net/core/sock_diag.c
@@ -69,7 +69,7 @@ int sock_diag_put_filterinfo(bool may_report_filterinfo, struct sock *sk,
goto out;
fprog = filter->orig_prog;
- flen = sk_filter_proglen(fprog);
+ flen = bpf_classic_proglen(fprog);
attr = nla_reserve(skb, attrtype, flen);
if (attr == NULL) {
--
1.7.9.5
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v4 net-next 3/5] net: filter: rename sk_chk_filter() -> bpf_check_classic()
2014-07-31 3:34 [PATCH v4 net-next 0/5] net: filter: split sk_filter into socket and bpf, cleanup names Alexei Starovoitov
2014-07-31 3:34 ` [PATCH v4 net-next 1/5] net: filter: simplify socket charging Alexei Starovoitov
2014-07-31 3:34 ` [PATCH v4 net-next 2/5] net: filter: rename sk_filter_proglen -> bpf_classic_proglen Alexei Starovoitov
@ 2014-07-31 3:34 ` Alexei Starovoitov
2014-07-31 3:34 ` [PATCH v4 net-next 4/5] net: filter: rename sk_convert_filter() -> bpf_convert_filter() Alexei Starovoitov
` (2 subsequent siblings)
5 siblings, 0 replies; 14+ messages in thread
From: Alexei Starovoitov @ 2014-07-31 3:34 UTC (permalink / raw)
To: David S. Miller
Cc: Daniel Borkmann, Willem de Bruijn, Pablo Neira Ayuso, Kees Cook,
netdev, linux-kernel, netfilter-devel
trivial rename to indicate that this functions performs classic BPF checking
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
---
Documentation/networking/filter.txt | 2 +-
include/linux/filter.h | 2 +-
kernel/bpf/core.c | 2 +-
kernel/seccomp.c | 4 ++--
net/core/filter.c | 10 +++++-----
5 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/Documentation/networking/filter.txt b/Documentation/networking/filter.txt
index ee78eba78a9d..712068be8171 100644
--- a/Documentation/networking/filter.txt
+++ b/Documentation/networking/filter.txt
@@ -591,7 +591,7 @@ sk_unattached_filter_destroy() for destroying it. The macro
SK_RUN_FILTER(filter, ctx) transparently invokes eBPF interpreter or JITed
code to run the filter. 'filter' is a pointer to struct sk_filter that we
got from sk_unattached_filter_create(), and 'ctx' the given context (e.g.
-skb pointer). All constraints and restrictions from sk_chk_filter() apply
+skb pointer). All constraints and restrictions from bpf_check_classic() apply
before a conversion to the new layout is being done behind the scenes!
Currently, the classic BPF format is being used for JITing on most of the
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 3769341a745d..c4d0be4c5e75 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -361,7 +361,7 @@ void sk_unattached_filter_destroy(struct sk_filter *fp);
int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk);
int sk_detach_filter(struct sock *sk);
-int sk_chk_filter(const struct sock_filter *filter, unsigned int flen);
+int bpf_check_classic(const struct sock_filter *filter, unsigned int flen);
int sk_get_filter(struct sock *sk, struct sock_filter __user *filter,
unsigned int len);
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 265a02cc822d..b479807ec383 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -18,7 +18,7 @@
* 2 of the License, or (at your option) any later version.
*
* Andi Kleen - Fix a few bad bugs and races.
- * Kris Katterjohn - Added many additional checks in sk_chk_filter()
+ * Kris Katterjohn - Added many additional checks in bpf_check_classic()
*/
#include <linux/filter.h>
#include <linux/skbuff.h>
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index 565743db5384..f4a77d23f209 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -87,7 +87,7 @@ static void populate_seccomp_data(struct seccomp_data *sd)
* @filter: filter to verify
* @flen: length of filter
*
- * Takes a previously checked filter (by sk_chk_filter) and
+ * Takes a previously checked filter (by bpf_check_classic) and
* redirects all filter code that loads struct sk_buff data
* and related data through seccomp_bpf_load. It also
* enforces length and alignment checking of those loads.
@@ -239,7 +239,7 @@ static long seccomp_attach_filter(struct sock_fprog *fprog)
goto free_prog;
/* Check and rewrite the fprog via the skb checker */
- ret = sk_chk_filter(fp, fprog->len);
+ ret = bpf_check_classic(fp, fprog->len);
if (ret)
goto free_prog;
diff --git a/net/core/filter.c b/net/core/filter.c
index d6cb287e4f59..5740ea08a3ad 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -18,7 +18,7 @@
* 2 of the License, or (at your option) any later version.
*
* Andi Kleen - Fix a few bad bugs and races.
- * Kris Katterjohn - Added many additional checks in sk_chk_filter()
+ * Kris Katterjohn - Added many additional checks in bpf_check_classic()
*/
#include <linux/module.h>
@@ -721,7 +721,7 @@ static bool chk_code_allowed(u16 code_to_probe)
}
/**
- * sk_chk_filter - verify socket filter code
+ * bpf_check_classic - verify socket filter code
* @filter: filter to verify
* @flen: length of filter
*
@@ -734,7 +734,7 @@ static bool chk_code_allowed(u16 code_to_probe)
*
* Returns 0 if the rule set is legal or -EINVAL if not.
*/
-int sk_chk_filter(const struct sock_filter *filter, unsigned int flen)
+int bpf_check_classic(const struct sock_filter *filter, unsigned int flen)
{
bool anc_found;
int pc;
@@ -808,7 +808,7 @@ int sk_chk_filter(const struct sock_filter *filter, unsigned int flen)
return -EINVAL;
}
-EXPORT_SYMBOL(sk_chk_filter);
+EXPORT_SYMBOL(bpf_check_classic);
static int sk_store_orig_filter(struct sk_filter *fp,
const struct sock_fprog *fprog)
@@ -968,7 +968,7 @@ static struct sk_filter *__sk_prepare_filter(struct sk_filter *fp)
fp->bpf_func = NULL;
fp->jited = 0;
- err = sk_chk_filter(fp->insns, fp->len);
+ err = bpf_check_classic(fp->insns, fp->len);
if (err) {
__sk_filter_release(fp);
return ERR_PTR(err);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v4 net-next 4/5] net: filter: rename sk_convert_filter() -> bpf_convert_filter()
2014-07-31 3:34 [PATCH v4 net-next 0/5] net: filter: split sk_filter into socket and bpf, cleanup names Alexei Starovoitov
` (2 preceding siblings ...)
2014-07-31 3:34 ` [PATCH v4 net-next 3/5] net: filter: rename sk_chk_filter() -> bpf_check_classic() Alexei Starovoitov
@ 2014-07-31 3:34 ` Alexei Starovoitov
2014-07-31 3:34 ` [PATCH v4 net-next 5/5] net: filter: split 'struct sk_filter' into socket and bpf parts Alexei Starovoitov
2014-08-02 22:09 ` [PATCH v4 net-next 0/5] net: filter: split sk_filter into socket and bpf, cleanup names David Miller
5 siblings, 0 replies; 14+ messages in thread
From: Alexei Starovoitov @ 2014-07-31 3:34 UTC (permalink / raw)
To: David S. Miller
Cc: Daniel Borkmann, Willem de Bruijn, Pablo Neira Ayuso, Kees Cook,
netdev, linux-kernel, netfilter-devel
to indicate that this function is converting classic BPF into eBPF
and not related to sockets
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
---
arch/x86/net/bpf_jit_comp.c | 2 +-
include/linux/filter.h | 4 ++--
kernel/bpf/core.c | 2 +-
kernel/seccomp.c | 4 ++--
net/core/filter.c | 16 ++++++++--------
5 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index 71737a83f022..e2ecc1380b3d 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -235,7 +235,7 @@ static int do_jit(struct sk_filter *bpf_prog, int *addrs, u8 *image,
/* mov qword ptr [rbp-X],rbx */
EMIT3_off32(0x48, 0x89, 0x9D, -stacksize);
- /* sk_convert_filter() maps classic BPF register X to R7 and uses R8
+ /* bpf_convert_filter() maps classic BPF register X to R7 and uses R8
* as temporary, so all tcpdump filters need to spill/fill R7(r13) and
* R8(r14). R9(r15) spill could be made conditional, but there is only
* one 'bpf_error' return path out of helper functions inside bpf_jit.S
diff --git a/include/linux/filter.h b/include/linux/filter.h
index c4d0be4c5e75..7cb9b40e9a2f 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -351,8 +351,8 @@ int sk_filter(struct sock *sk, struct sk_buff *skb);
void sk_filter_select_runtime(struct sk_filter *fp);
void sk_filter_free(struct sk_filter *fp);
-int sk_convert_filter(struct sock_filter *prog, int len,
- struct bpf_insn *new_prog, int *new_len);
+int bpf_convert_filter(struct sock_filter *prog, int len,
+ struct bpf_insn *new_prog, int *new_len);
int sk_unattached_filter_create(struct sk_filter **pfp,
struct sock_fprog_kern *fprog);
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index b479807ec383..188ac5ba3900 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -446,7 +446,7 @@ load_word:
/* BPF_LD + BPD_ABS and BPF_LD + BPF_IND insns are
* only appearing in the programs where ctx ==
* skb. All programs keep 'ctx' in regs[BPF_REG_CTX]
- * == BPF_R6, sk_convert_filter() saves it in BPF_R6,
+ * == BPF_R6, bpf_convert_filter() saves it in BPF_R6,
* internal BPF verifier will check that BPF_R6 ==
* ctx.
*
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index f4a77d23f209..33a3a97e2b58 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -249,7 +249,7 @@ static long seccomp_attach_filter(struct sock_fprog *fprog)
goto free_prog;
/* Convert 'sock_filter' insns to 'bpf_insn' insns */
- ret = sk_convert_filter(fp, fprog->len, NULL, &new_len);
+ ret = bpf_convert_filter(fp, fprog->len, NULL, &new_len);
if (ret)
goto free_prog;
@@ -265,7 +265,7 @@ static long seccomp_attach_filter(struct sock_fprog *fprog)
if (!filter->prog)
goto free_filter;
- ret = sk_convert_filter(fp, fprog->len, filter->prog->insnsi, &new_len);
+ ret = bpf_convert_filter(fp, fprog->len, filter->prog->insnsi, &new_len);
if (ret)
goto free_filter_prog;
kfree(fp);
diff --git a/net/core/filter.c b/net/core/filter.c
index 5740ea08a3ad..6ac901613bee 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -312,7 +312,7 @@ static bool convert_bpf_extensions(struct sock_filter *fp,
}
/**
- * sk_convert_filter - convert filter program
+ * bpf_convert_filter - convert filter program
* @prog: the user passed filter program
* @len: the length of the user passed filter program
* @new_prog: buffer where converted program will be stored
@@ -322,12 +322,12 @@ static bool convert_bpf_extensions(struct sock_filter *fp,
* Conversion workflow:
*
* 1) First pass for calculating the new program length:
- * sk_convert_filter(old_prog, old_len, NULL, &new_len)
+ * bpf_convert_filter(old_prog, old_len, NULL, &new_len)
*
* 2) 2nd pass to remap in two passes: 1st pass finds new
* jump offsets, 2nd pass remapping:
* new_prog = kmalloc(sizeof(struct bpf_insn) * new_len);
- * sk_convert_filter(old_prog, old_len, new_prog, &new_len);
+ * bpf_convert_filter(old_prog, old_len, new_prog, &new_len);
*
* User BPF's register A is mapped to our BPF register 6, user BPF
* register X is mapped to BPF register 7; frame pointer is always
@@ -335,8 +335,8 @@ static bool convert_bpf_extensions(struct sock_filter *fp,
* for socket filters: ctx == 'struct sk_buff *', for seccomp:
* ctx == 'struct seccomp_data *'.
*/
-int sk_convert_filter(struct sock_filter *prog, int len,
- struct bpf_insn *new_prog, int *new_len)
+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;
@@ -921,7 +921,7 @@ static struct sk_filter *__sk_migrate_filter(struct sk_filter *fp)
}
/* 1st pass: calculate the new program length. */
- err = sk_convert_filter(old_prog, old_len, NULL, &new_len);
+ err = bpf_convert_filter(old_prog, old_len, NULL, &new_len);
if (err)
goto out_err_free;
@@ -940,9 +940,9 @@ static struct sk_filter *__sk_migrate_filter(struct sk_filter *fp)
fp->len = new_len;
/* 2nd pass: remap sock_filter insns into bpf_insn insns. */
- err = sk_convert_filter(old_prog, old_len, fp->insnsi, &new_len);
+ err = bpf_convert_filter(old_prog, old_len, fp->insnsi, &new_len);
if (err)
- /* 2nd sk_convert_filter() can fail only if it fails
+ /* 2nd bpf_convert_filter() can fail only if it fails
* to allocate memory, remapping must succeed. Note,
* that at this time old_fp has already been released
* by krealloc().
--
1.7.9.5
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v4 net-next 5/5] net: filter: split 'struct sk_filter' into socket and bpf parts
2014-07-31 3:34 [PATCH v4 net-next 0/5] net: filter: split sk_filter into socket and bpf, cleanup names Alexei Starovoitov
` (3 preceding siblings ...)
2014-07-31 3:34 ` [PATCH v4 net-next 4/5] net: filter: rename sk_convert_filter() -> bpf_convert_filter() Alexei Starovoitov
@ 2014-07-31 3:34 ` Alexei Starovoitov
2014-07-31 19:40 ` Pablo Neira Ayuso
2014-08-02 22:09 ` [PATCH v4 net-next 0/5] net: filter: split sk_filter into socket and bpf, cleanup names David Miller
5 siblings, 1 reply; 14+ messages in thread
From: Alexei Starovoitov @ 2014-07-31 3:34 UTC (permalink / raw)
To: David S. Miller
Cc: Daniel Borkmann, Willem de Bruijn, Pablo Neira Ayuso, Kees Cook,
netdev, linux-kernel, netfilter-devel
clean up names related to socket filtering and bpf in the following way:
- everything that deals with sockets keeps 'sk_*' prefix
- everything that is pure BPF is changed to 'bpf_*' prefix
split 'struct sk_filter' into
struct sk_filter {
atomic_t refcnt;
struct rcu_head rcu;
struct bpf_prog *prog;
};
and
struct bpf_prog {
u32 jited:1,
len:31;
struct sock_fprog_kern *orig_prog;
unsigned int (*bpf_func)(const struct sk_buff *skb,
const struct bpf_insn *filter);
union {
struct sock_filter insns[0];
struct bpf_insn insnsi[0];
struct work_struct work;
};
};
so that 'struct bpf_prog' can be used independent of sockets and cleans up
'unattached' bpf use cases
split SK_RUN_FILTER macro into:
SK_RUN_FILTER to be used with 'struct sk_filter *' and
BPF_PROG_RUN to be used with 'struct bpf_prog *'
__sk_filter_release(struct sk_filter *) gains
__bpf_prog_release(struct bpf_prog *) helper function
also perform related renames for the functions that work
with 'struct bpf_prog *', since they're on the same lines:
sk_filter_size -> bpf_prog_size
sk_filter_select_runtime -> bpf_prog_select_runtime
sk_filter_free -> bpf_prog_free
sk_unattached_filter_create -> bpf_prog_create
sk_unattached_filter_destroy -> bpf_prog_destroy
sk_store_orig_filter -> bpf_prog_store_orig_filter
sk_release_orig_filter -> bpf_release_orig_filter
__sk_migrate_filter -> bpf_migrate_filter
__sk_prepare_filter -> bpf_prepare_filter
API for attaching classic BPF to a socket stays the same:
sk_attach_filter(prog, struct sock *)/sk_detach_filter(struct sock *)
and SK_RUN_FILTER(struct sk_filter *, ctx) to execute a program
which is used by sockets, tun, af_packet
API for 'unattached' BPF programs becomes:
bpf_prog_create(struct bpf_prog **)/bpf_prog_destroy(struct bpf_prog *)
and BPF_PROG_RUN(struct bpf_prog *, ctx) to execute a program
which is used by isdn, ppp, team, seccomp, ptp, xt_bpf, cls_bpf, test_bpf
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
---
Documentation/networking/filter.txt | 10 ++--
arch/arm/net/bpf_jit_32.c | 8 +--
arch/mips/net/bpf_jit.c | 8 +--
arch/powerpc/net/bpf_jit_comp.c | 8 +--
arch/s390/net/bpf_jit_comp.c | 4 +-
arch/sparc/net/bpf_jit_comp.c | 4 +-
arch/x86/net/bpf_jit_comp.c | 12 ++--
drivers/isdn/i4l/isdn_ppp.c | 26 ++++-----
drivers/net/ppp/ppp_generic.c | 28 ++++-----
drivers/net/team/team_mode_loadbalance.c | 14 ++---
include/linux/filter.h | 40 +++++++------
include/linux/isdn_ppp.h | 4 +-
include/uapi/linux/netfilter/xt_bpf.h | 4 +-
kernel/bpf/core.c | 30 +++++-----
kernel/seccomp.c | 10 ++--
lib/test_bpf.c | 24 ++++----
net/core/filter.c | 92 +++++++++++++++++-------------
net/core/ptp_classifier.c | 6 +-
net/core/sock_diag.c | 2 +-
net/netfilter/xt_bpf.c | 6 +-
net/sched/cls_bpf.c | 12 ++--
21 files changed, 183 insertions(+), 169 deletions(-)
diff --git a/Documentation/networking/filter.txt b/Documentation/networking/filter.txt
index 712068be8171..c48a9704bda8 100644
--- a/Documentation/networking/filter.txt
+++ b/Documentation/networking/filter.txt
@@ -586,11 +586,11 @@ team driver's classifier for its load-balancing mode, netfilter's xt_bpf
extension, PTP dissector/classifier, and much more. They are all internally
converted by the kernel into the new instruction set representation and run
in the eBPF interpreter. For in-kernel handlers, this all works transparently
-by using sk_unattached_filter_create() for setting up the filter, resp.
-sk_unattached_filter_destroy() for destroying it. The macro
-SK_RUN_FILTER(filter, ctx) transparently invokes eBPF interpreter or JITed
-code to run the filter. 'filter' is a pointer to struct sk_filter that we
-got from sk_unattached_filter_create(), and 'ctx' the given context (e.g.
+by using bpf_prog_create() for setting up the filter, resp.
+bpf_prog_destroy() for destroying it. The macro
+BPF_PROG_RUN(filter, ctx) transparently invokes eBPF interpreter or JITed
+code to run the filter. 'filter' is a pointer to struct bpf_prog that we
+got from bpf_prog_create(), and 'ctx' the given context (e.g.
skb pointer). All constraints and restrictions from bpf_check_classic() apply
before a conversion to the new layout is being done behind the scenes!
diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
index fb5503ce016f..a37b989a2f91 100644
--- a/arch/arm/net/bpf_jit_32.c
+++ b/arch/arm/net/bpf_jit_32.c
@@ -56,7 +56,7 @@
#define FLAG_NEED_X_RESET (1 << 0)
struct jit_ctx {
- const struct sk_filter *skf;
+ const struct bpf_prog *skf;
unsigned idx;
unsigned prologue_bytes;
int ret0_fp_idx;
@@ -465,7 +465,7 @@ static inline void update_on_xread(struct jit_ctx *ctx)
static int build_body(struct jit_ctx *ctx)
{
void *load_func[] = {jit_get_skb_b, jit_get_skb_h, jit_get_skb_w};
- const struct sk_filter *prog = ctx->skf;
+ const struct bpf_prog *prog = ctx->skf;
const struct sock_filter *inst;
unsigned i, load_order, off, condt;
int imm12;
@@ -857,7 +857,7 @@ b_epilogue:
}
-void bpf_jit_compile(struct sk_filter *fp)
+void bpf_jit_compile(struct bpf_prog *fp)
{
struct jit_ctx ctx;
unsigned tmp_idx;
@@ -926,7 +926,7 @@ out:
return;
}
-void bpf_jit_free(struct sk_filter *fp)
+void bpf_jit_free(struct bpf_prog *fp)
{
if (fp->jited)
module_free(NULL, fp->bpf_func);
diff --git a/arch/mips/net/bpf_jit.c b/arch/mips/net/bpf_jit.c
index b87390a56a2f..05a56619ece2 100644
--- a/arch/mips/net/bpf_jit.c
+++ b/arch/mips/net/bpf_jit.c
@@ -131,7 +131,7 @@
* @target: Memory location for the compiled filter
*/
struct jit_ctx {
- const struct sk_filter *skf;
+ const struct bpf_prog *skf;
unsigned int prologue_bytes;
u32 idx;
u32 flags;
@@ -789,7 +789,7 @@ static int pkt_type_offset(void)
static int build_body(struct jit_ctx *ctx)
{
void *load_func[] = {jit_get_skb_b, jit_get_skb_h, jit_get_skb_w};
- const struct sk_filter *prog = ctx->skf;
+ const struct bpf_prog *prog = ctx->skf;
const struct sock_filter *inst;
unsigned int i, off, load_order, condt;
u32 k, b_off __maybe_unused;
@@ -1369,7 +1369,7 @@ jmp_cmp:
int bpf_jit_enable __read_mostly;
-void bpf_jit_compile(struct sk_filter *fp)
+void bpf_jit_compile(struct bpf_prog *fp)
{
struct jit_ctx ctx;
unsigned int alloc_size, tmp_idx;
@@ -1423,7 +1423,7 @@ out:
kfree(ctx.offsets);
}
-void bpf_jit_free(struct sk_filter *fp)
+void bpf_jit_free(struct bpf_prog *fp)
{
if (fp->jited)
module_free(NULL, fp->bpf_func);
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index 82e82cadcde5..3afa6f4c1957 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -25,7 +25,7 @@ static inline void bpf_flush_icache(void *start, void *end)
flush_icache_range((unsigned long)start, (unsigned long)end);
}
-static void bpf_jit_build_prologue(struct sk_filter *fp, u32 *image,
+static void bpf_jit_build_prologue(struct bpf_prog *fp, u32 *image,
struct codegen_context *ctx)
{
int i;
@@ -121,7 +121,7 @@ static void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx)
((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative_offset : func) : func##_positive_offset)
/* Assemble the body code between the prologue & epilogue. */
-static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
+static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
struct codegen_context *ctx,
unsigned int *addrs)
{
@@ -569,7 +569,7 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
return 0;
}
-void bpf_jit_compile(struct sk_filter *fp)
+void bpf_jit_compile(struct bpf_prog *fp)
{
unsigned int proglen;
unsigned int alloclen;
@@ -693,7 +693,7 @@ out:
return;
}
-void bpf_jit_free(struct sk_filter *fp)
+void bpf_jit_free(struct bpf_prog *fp)
{
if (fp->jited)
module_free(NULL, fp->bpf_func);
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
index a2cbd875543a..61e45b7c04d7 100644
--- a/arch/s390/net/bpf_jit_comp.c
+++ b/arch/s390/net/bpf_jit_comp.c
@@ -812,7 +812,7 @@ static struct bpf_binary_header *bpf_alloc_binary(unsigned int bpfsize,
return header;
}
-void bpf_jit_compile(struct sk_filter *fp)
+void bpf_jit_compile(struct bpf_prog *fp)
{
struct bpf_binary_header *header = NULL;
unsigned long size, prg_len, lit_len;
@@ -875,7 +875,7 @@ out:
kfree(addrs);
}
-void bpf_jit_free(struct sk_filter *fp)
+void bpf_jit_free(struct bpf_prog *fp)
{
unsigned long addr = (unsigned long)fp->bpf_func & PAGE_MASK;
struct bpf_binary_header *header = (void *)addr;
diff --git a/arch/sparc/net/bpf_jit_comp.c b/arch/sparc/net/bpf_jit_comp.c
index 892a102671ad..1f76c22a6a75 100644
--- a/arch/sparc/net/bpf_jit_comp.c
+++ b/arch/sparc/net/bpf_jit_comp.c
@@ -354,7 +354,7 @@ do { *prog++ = BR_OPC | WDISP22(OFF); \
* emit_jump() calls with adjusted offsets.
*/
-void bpf_jit_compile(struct sk_filter *fp)
+void bpf_jit_compile(struct bpf_prog *fp)
{
unsigned int cleanup_addr, proglen, oldproglen = 0;
u32 temp[8], *prog, *func, seen = 0, pass;
@@ -808,7 +808,7 @@ out:
return;
}
-void bpf_jit_free(struct sk_filter *fp)
+void bpf_jit_free(struct bpf_prog *fp)
{
if (fp->jited)
module_free(NULL, fp->bpf_func);
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index e2ecc1380b3d..5c8cb8043c5a 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -211,7 +211,7 @@ struct jit_context {
bool seen_ld_abs;
};
-static int do_jit(struct sk_filter *bpf_prog, int *addrs, u8 *image,
+static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
int oldproglen, struct jit_context *ctx)
{
struct bpf_insn *insn = bpf_prog->insnsi;
@@ -841,7 +841,7 @@ common_load: ctx->seen_ld_abs = true;
/* By design x64 JIT should support all BPF instructions
* This error will be seen if new instruction was added
* to interpreter, but not to JIT
- * or if there is junk in sk_filter
+ * or if there is junk in bpf_prog
*/
pr_err("bpf_jit: unknown opcode %02x\n", insn->code);
return -EINVAL;
@@ -862,11 +862,11 @@ common_load: ctx->seen_ld_abs = true;
return proglen;
}
-void bpf_jit_compile(struct sk_filter *prog)
+void bpf_jit_compile(struct bpf_prog *prog)
{
}
-void bpf_int_jit_compile(struct sk_filter *prog)
+void bpf_int_jit_compile(struct bpf_prog *prog)
{
struct bpf_binary_header *header = NULL;
int proglen, oldproglen = 0;
@@ -932,7 +932,7 @@ out:
static void bpf_jit_free_deferred(struct work_struct *work)
{
- struct sk_filter *fp = container_of(work, struct sk_filter, work);
+ struct bpf_prog *fp = container_of(work, struct bpf_prog, work);
unsigned long addr = (unsigned long)fp->bpf_func & PAGE_MASK;
struct bpf_binary_header *header = (void *)addr;
@@ -941,7 +941,7 @@ static void bpf_jit_free_deferred(struct work_struct *work)
kfree(fp);
}
-void bpf_jit_free(struct sk_filter *fp)
+void bpf_jit_free(struct bpf_prog *fp)
{
if (fp->jited) {
INIT_WORK(&fp->work, bpf_jit_free_deferred);
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
index 62f0688d45a5..c4198fa490bf 100644
--- a/drivers/isdn/i4l/isdn_ppp.c
+++ b/drivers/isdn/i4l/isdn_ppp.c
@@ -379,12 +379,12 @@ isdn_ppp_release(int min, struct file *file)
#endif
#ifdef CONFIG_IPPP_FILTER
if (is->pass_filter) {
- sk_unattached_filter_destroy(is->pass_filter);
+ bpf_prog_destroy(is->pass_filter);
is->pass_filter = NULL;
}
if (is->active_filter) {
- sk_unattached_filter_destroy(is->active_filter);
+ bpf_prog_destroy(is->active_filter);
is->active_filter = NULL;
}
#endif
@@ -639,12 +639,11 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
fprog.filter = code;
if (is->pass_filter) {
- sk_unattached_filter_destroy(is->pass_filter);
+ bpf_prog_destroy(is->pass_filter);
is->pass_filter = NULL;
}
if (fprog.filter != NULL)
- err = sk_unattached_filter_create(&is->pass_filter,
- &fprog);
+ err = bpf_prog_create(&is->pass_filter, &fprog);
else
err = 0;
kfree(code);
@@ -664,12 +663,11 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
fprog.filter = code;
if (is->active_filter) {
- sk_unattached_filter_destroy(is->active_filter);
+ bpf_prog_destroy(is->active_filter);
is->active_filter = NULL;
}
if (fprog.filter != NULL)
- err = sk_unattached_filter_create(&is->active_filter,
- &fprog);
+ err = bpf_prog_create(&is->active_filter, &fprog);
else
err = 0;
kfree(code);
@@ -1174,14 +1172,14 @@ isdn_ppp_push_higher(isdn_net_dev *net_dev, isdn_net_local *lp, struct sk_buff *
}
if (is->pass_filter
- && SK_RUN_FILTER(is->pass_filter, skb) == 0) {
+ && BPF_PROG_RUN(is->pass_filter, skb) == 0) {
if (is->debug & 0x2)
printk(KERN_DEBUG "IPPP: inbound frame filtered.\n");
kfree_skb(skb);
return;
}
if (!(is->active_filter
- && SK_RUN_FILTER(is->active_filter, skb) == 0)) {
+ && BPF_PROG_RUN(is->active_filter, skb) == 0)) {
if (is->debug & 0x2)
printk(KERN_DEBUG "IPPP: link-active filter: resetting huptimer.\n");
lp->huptimer = 0;
@@ -1320,14 +1318,14 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
}
if (ipt->pass_filter
- && SK_RUN_FILTER(ipt->pass_filter, skb) == 0) {
+ && BPF_PROG_RUN(ipt->pass_filter, skb) == 0) {
if (ipt->debug & 0x4)
printk(KERN_DEBUG "IPPP: outbound frame filtered.\n");
kfree_skb(skb);
goto unlock;
}
if (!(ipt->active_filter
- && SK_RUN_FILTER(ipt->active_filter, skb) == 0)) {
+ && BPF_PROG_RUN(ipt->active_filter, skb) == 0)) {
if (ipt->debug & 0x4)
printk(KERN_DEBUG "IPPP: link-active filter: resetting huptimer.\n");
lp->huptimer = 0;
@@ -1517,9 +1515,9 @@ int isdn_ppp_autodial_filter(struct sk_buff *skb, isdn_net_local *lp)
}
drop |= is->pass_filter
- && SK_RUN_FILTER(is->pass_filter, skb) == 0;
+ && BPF_PROG_RUN(is->pass_filter, skb) == 0;
drop |= is->active_filter
- && SK_RUN_FILTER(is->active_filter, skb) == 0;
+ && BPF_PROG_RUN(is->active_filter, skb) == 0;
skb_push(skb, IPPP_MAX_HEADER - 4);
return drop;
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index 765248b42a0a..fa0d71727894 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -143,8 +143,8 @@ struct ppp {
struct sk_buff_head mrq; /* MP: receive reconstruction queue */
#endif /* CONFIG_PPP_MULTILINK */
#ifdef CONFIG_PPP_FILTER
- struct sk_filter *pass_filter; /* filter for packets to pass */
- struct sk_filter *active_filter;/* filter for pkts to reset idle */
+ struct bpf_prog *pass_filter; /* filter for packets to pass */
+ struct bpf_prog *active_filter; /* filter for pkts to reset idle */
#endif /* CONFIG_PPP_FILTER */
struct net *ppp_net; /* the net we belong to */
struct ppp_link_stats stats64; /* 64 bit network stats */
@@ -762,12 +762,12 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
ppp_lock(ppp);
if (ppp->pass_filter) {
- sk_unattached_filter_destroy(ppp->pass_filter);
+ bpf_prog_destroy(ppp->pass_filter);
ppp->pass_filter = NULL;
}
if (fprog.filter != NULL)
- err = sk_unattached_filter_create(&ppp->pass_filter,
- &fprog);
+ err = bpf_prog_create(&ppp->pass_filter,
+ &fprog);
else
err = 0;
kfree(code);
@@ -788,12 +788,12 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
ppp_lock(ppp);
if (ppp->active_filter) {
- sk_unattached_filter_destroy(ppp->active_filter);
+ bpf_prog_destroy(ppp->active_filter);
ppp->active_filter = NULL;
}
if (fprog.filter != NULL)
- err = sk_unattached_filter_create(&ppp->active_filter,
- &fprog);
+ err = bpf_prog_create(&ppp->active_filter,
+ &fprog);
else
err = 0;
kfree(code);
@@ -1205,7 +1205,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
a four-byte PPP header on each packet */
*skb_push(skb, 2) = 1;
if (ppp->pass_filter &&
- SK_RUN_FILTER(ppp->pass_filter, skb) == 0) {
+ BPF_PROG_RUN(ppp->pass_filter, skb) == 0) {
if (ppp->debug & 1)
netdev_printk(KERN_DEBUG, ppp->dev,
"PPP: outbound frame "
@@ -1215,7 +1215,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
}
/* if this packet passes the active filter, record the time */
if (!(ppp->active_filter &&
- SK_RUN_FILTER(ppp->active_filter, skb) == 0))
+ BPF_PROG_RUN(ppp->active_filter, skb) == 0))
ppp->last_xmit = jiffies;
skb_pull(skb, 2);
#else
@@ -1839,7 +1839,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
*skb_push(skb, 2) = 0;
if (ppp->pass_filter &&
- SK_RUN_FILTER(ppp->pass_filter, skb) == 0) {
+ BPF_PROG_RUN(ppp->pass_filter, skb) == 0) {
if (ppp->debug & 1)
netdev_printk(KERN_DEBUG, ppp->dev,
"PPP: inbound frame "
@@ -1848,7 +1848,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
return;
}
if (!(ppp->active_filter &&
- SK_RUN_FILTER(ppp->active_filter, skb) == 0))
+ BPF_PROG_RUN(ppp->active_filter, skb) == 0))
ppp->last_recv = jiffies;
__skb_pull(skb, 2);
} else
@@ -2829,12 +2829,12 @@ static void ppp_destroy_interface(struct ppp *ppp)
#endif /* CONFIG_PPP_MULTILINK */
#ifdef CONFIG_PPP_FILTER
if (ppp->pass_filter) {
- sk_unattached_filter_destroy(ppp->pass_filter);
+ bpf_prog_destroy(ppp->pass_filter);
ppp->pass_filter = NULL;
}
if (ppp->active_filter) {
- sk_unattached_filter_destroy(ppp->active_filter);
+ bpf_prog_destroy(ppp->active_filter);
ppp->active_filter = NULL;
}
#endif /* CONFIG_PPP_FILTER */
diff --git a/drivers/net/team/team_mode_loadbalance.c b/drivers/net/team/team_mode_loadbalance.c
index 7106f3456439..30796e2dc4a2 100644
--- a/drivers/net/team/team_mode_loadbalance.c
+++ b/drivers/net/team/team_mode_loadbalance.c
@@ -58,7 +58,7 @@ struct lb_priv_ex {
};
struct lb_priv {
- struct sk_filter __rcu *fp;
+ struct bpf_prog __rcu *fp;
lb_select_tx_port_func_t __rcu *select_tx_port_func;
struct lb_pcpu_stats __percpu *pcpu_stats;
struct lb_priv_ex *ex; /* priv extension */
@@ -174,14 +174,14 @@ static lb_select_tx_port_func_t *lb_select_tx_port_get_func(const char *name)
static unsigned int lb_get_skb_hash(struct lb_priv *lb_priv,
struct sk_buff *skb)
{
- struct sk_filter *fp;
+ struct bpf_prog *fp;
uint32_t lhash;
unsigned char *c;
fp = rcu_dereference_bh(lb_priv->fp);
if (unlikely(!fp))
return 0;
- lhash = SK_RUN_FILTER(fp, skb);
+ lhash = BPF_PROG_RUN(fp, skb);
c = (char *) &lhash;
return c[0] ^ c[1] ^ c[2] ^ c[3];
}
@@ -271,8 +271,8 @@ static void __fprog_destroy(struct sock_fprog_kern *fprog)
static int lb_bpf_func_set(struct team *team, struct team_gsetter_ctx *ctx)
{
struct lb_priv *lb_priv = get_lb_priv(team);
- struct sk_filter *fp = NULL;
- struct sk_filter *orig_fp;
+ struct bpf_prog *fp = NULL;
+ struct bpf_prog *orig_fp;
struct sock_fprog_kern *fprog = NULL;
int err;
@@ -281,7 +281,7 @@ static int lb_bpf_func_set(struct team *team, struct team_gsetter_ctx *ctx)
ctx->data.bin_val.ptr);
if (err)
return err;
- err = sk_unattached_filter_create(&fp, fprog);
+ err = bpf_prog_create(&fp, fprog);
if (err) {
__fprog_destroy(fprog);
return err;
@@ -300,7 +300,7 @@ static int lb_bpf_func_set(struct team *team, struct team_gsetter_ctx *ctx)
if (orig_fp) {
synchronize_rcu();
- sk_unattached_filter_destroy(orig_fp);
+ bpf_prog_destroy(orig_fp);
}
return 0;
}
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 7cb9b40e9a2f..a5227ab8ccb1 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -296,7 +296,8 @@ enum {
})
/* Macro to invoke filter function. */
-#define SK_RUN_FILTER(filter, ctx) (*filter->bpf_func)(ctx, filter->insnsi)
+#define SK_RUN_FILTER(filter, ctx) \
+ (*filter->prog->bpf_func)(ctx, filter->prog->insnsi)
struct bpf_insn {
__u8 code; /* opcode */
@@ -323,12 +324,10 @@ struct sk_buff;
struct sock;
struct seccomp_data;
-struct sk_filter {
- atomic_t refcnt;
+struct bpf_prog {
u32 jited:1, /* Is our filter JIT'ed? */
len:31; /* Number of filter blocks */
struct sock_fprog_kern *orig_prog; /* Original BPF program */
- struct rcu_head rcu;
unsigned int (*bpf_func)(const struct sk_buff *skb,
const struct bpf_insn *filter);
union {
@@ -338,25 +337,32 @@ struct sk_filter {
};
};
-static inline unsigned int sk_filter_size(unsigned int proglen)
+struct sk_filter {
+ atomic_t refcnt;
+ struct rcu_head rcu;
+ struct bpf_prog *prog;
+};
+
+#define BPF_PROG_RUN(filter, ctx) (*filter->bpf_func)(ctx, filter->insnsi)
+
+static inline unsigned int bpf_prog_size(unsigned int proglen)
{
- return max(sizeof(struct sk_filter),
- offsetof(struct sk_filter, insns[proglen]));
+ return max(sizeof(struct bpf_prog),
+ offsetof(struct bpf_prog, insns[proglen]));
}
#define bpf_classic_proglen(fprog) (fprog->len * sizeof(fprog->filter[0]))
int sk_filter(struct sock *sk, struct sk_buff *skb);
-void sk_filter_select_runtime(struct sk_filter *fp);
-void sk_filter_free(struct sk_filter *fp);
+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);
-int sk_unattached_filter_create(struct sk_filter **pfp,
- struct sock_fprog_kern *fprog);
-void sk_unattached_filter_destroy(struct sk_filter *fp);
+int bpf_prog_create(struct bpf_prog **pfp, struct sock_fprog_kern *fprog);
+void bpf_prog_destroy(struct bpf_prog *fp);
int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk);
int sk_detach_filter(struct sock *sk);
@@ -369,7 +375,7 @@ bool sk_filter_charge(struct sock *sk, struct sk_filter *fp);
void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp);
u64 __bpf_call_base(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5);
-void bpf_int_jit_compile(struct sk_filter *fp);
+void bpf_int_jit_compile(struct bpf_prog *fp);
#define BPF_ANC BIT(15)
@@ -423,8 +429,8 @@ static inline void *bpf_load_pointer(const struct sk_buff *skb, int k,
#include <linux/linkage.h>
#include <linux/printk.h>
-void bpf_jit_compile(struct sk_filter *fp);
-void bpf_jit_free(struct sk_filter *fp);
+void bpf_jit_compile(struct bpf_prog *fp);
+void bpf_jit_free(struct bpf_prog *fp);
static inline void bpf_jit_dump(unsigned int flen, unsigned int proglen,
u32 pass, void *image)
@@ -438,11 +444,11 @@ static inline void bpf_jit_dump(unsigned int flen, unsigned int proglen,
#else
#include <linux/slab.h>
-static inline void bpf_jit_compile(struct sk_filter *fp)
+static inline void bpf_jit_compile(struct bpf_prog *fp)
{
}
-static inline void bpf_jit_free(struct sk_filter *fp)
+static inline void bpf_jit_free(struct bpf_prog *fp)
{
kfree(fp);
}
diff --git a/include/linux/isdn_ppp.h b/include/linux/isdn_ppp.h
index 8e10f57f109f..a0070c6dfaf8 100644
--- a/include/linux/isdn_ppp.h
+++ b/include/linux/isdn_ppp.h
@@ -180,8 +180,8 @@ struct ippp_struct {
struct slcompress *slcomp;
#endif
#ifdef CONFIG_IPPP_FILTER
- struct sk_filter *pass_filter; /* filter for packets to pass */
- struct sk_filter *active_filter; /* filter for pkts to reset idle */
+ struct bpf_prog *pass_filter; /* filter for packets to pass */
+ struct bpf_prog *active_filter; /* filter for pkts to reset idle */
#endif
unsigned long debug;
struct isdn_ppp_compressor *compressor,*decompressor;
diff --git a/include/uapi/linux/netfilter/xt_bpf.h b/include/uapi/linux/netfilter/xt_bpf.h
index 2ec9fbcd06f9..1fad2c27ac32 100644
--- a/include/uapi/linux/netfilter/xt_bpf.h
+++ b/include/uapi/linux/netfilter/xt_bpf.h
@@ -6,14 +6,14 @@
#define XT_BPF_MAX_NUM_INSTR 64
-struct sk_filter;
+struct bpf_prog;
struct xt_bpf_info {
__u16 bpf_program_num_elem;
struct sock_filter bpf_program[XT_BPF_MAX_NUM_INSTR];
/* only used in the kernel */
- struct sk_filter *filter __attribute__((aligned(8)));
+ struct bpf_prog *filter __attribute__((aligned(8)));
};
#endif /*_XT_BPF_H */
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 188ac5ba3900..7f0dbcbb34af 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -73,15 +73,13 @@ noinline u64 __bpf_call_base(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5)
}
/**
- * __sk_run_filter - run a filter on a given context
- * @ctx: buffer to run the filter on
- * @insn: filter to apply
+ * __bpf_prog_run - run eBPF program on a given context
+ * @ctx: is the data we are operating on
+ * @insn: is the array of eBPF instructions
*
- * Decode and apply filter instructions to the skb->data. Return length to
- * keep, 0 for none. @ctx is the data we are operating on, @insn is the
- * array of filter instructions.
+ * Decode and execute eBPF instructions.
*/
-static unsigned int __sk_run_filter(void *ctx, const struct bpf_insn *insn)
+static unsigned int __bpf_prog_run(void *ctx, const struct bpf_insn *insn)
{
u64 stack[MAX_BPF_STACK / sizeof(u64)];
u64 regs[MAX_BPF_REG], tmp;
@@ -508,29 +506,29 @@ load_byte:
return 0;
}
-void __weak bpf_int_jit_compile(struct sk_filter *prog)
+void __weak bpf_int_jit_compile(struct bpf_prog *prog)
{
}
/**
- * sk_filter_select_runtime - select execution runtime for BPF program
- * @fp: sk_filter populated with internal BPF program
+ * bpf_prog_select_runtime - select execution runtime for BPF program
+ * @fp: bpf_prog populated with internal BPF program
*
* try to JIT internal BPF program, if JIT is not available select interpreter
- * BPF program will be executed via SK_RUN_FILTER() macro
+ * BPF program will be executed via BPF_PROG_RUN() macro
*/
-void sk_filter_select_runtime(struct sk_filter *fp)
+void bpf_prog_select_runtime(struct bpf_prog *fp)
{
- fp->bpf_func = (void *) __sk_run_filter;
+ fp->bpf_func = (void *) __bpf_prog_run;
/* Probe if internal BPF can be JITed */
bpf_int_jit_compile(fp);
}
-EXPORT_SYMBOL_GPL(sk_filter_select_runtime);
+EXPORT_SYMBOL_GPL(bpf_prog_select_runtime);
/* free internal BPF program */
-void sk_filter_free(struct sk_filter *fp)
+void bpf_prog_free(struct bpf_prog *fp)
{
bpf_jit_free(fp);
}
-EXPORT_SYMBOL_GPL(sk_filter_free);
+EXPORT_SYMBOL_GPL(bpf_prog_free);
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index 33a3a97e2b58..2f3fa2cc2eac 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -54,7 +54,7 @@
struct seccomp_filter {
atomic_t usage;
struct seccomp_filter *prev;
- struct sk_filter *prog;
+ struct bpf_prog *prog;
};
/* Limit any path through the tree to 256KB worth of instructions. */
@@ -187,7 +187,7 @@ static u32 seccomp_run_filters(int syscall)
* value always takes priority (ignoring the DATA).
*/
for (f = current->seccomp.filter; f; f = f->prev) {
- u32 cur_ret = SK_RUN_FILTER(f->prog, (void *)&sd);
+ u32 cur_ret = BPF_PROG_RUN(f->prog, (void *)&sd);
if ((cur_ret & SECCOMP_RET_ACTION) < (ret & SECCOMP_RET_ACTION))
ret = cur_ret;
@@ -260,7 +260,7 @@ static long seccomp_attach_filter(struct sock_fprog *fprog)
if (!filter)
goto free_prog;
- filter->prog = kzalloc(sk_filter_size(new_len),
+ filter->prog = kzalloc(bpf_prog_size(new_len),
GFP_KERNEL|__GFP_NOWARN);
if (!filter->prog)
goto free_filter;
@@ -273,7 +273,7 @@ static long seccomp_attach_filter(struct sock_fprog *fprog)
atomic_set(&filter->usage, 1);
filter->prog->len = new_len;
- sk_filter_select_runtime(filter->prog);
+ bpf_prog_select_runtime(filter->prog);
/*
* If there is an existing filter, make it the prev and don't drop its
@@ -337,7 +337,7 @@ void put_seccomp_filter(struct task_struct *tsk)
while (orig && atomic_dec_and_test(&orig->usage)) {
struct seccomp_filter *freeme = orig;
orig = orig->prev;
- sk_filter_free(freeme->prog);
+ bpf_prog_free(freeme->prog);
kfree(freeme);
}
}
diff --git a/lib/test_bpf.c b/lib/test_bpf.c
index 5f48623ee1a7..89e0345733bd 100644
--- a/lib/test_bpf.c
+++ b/lib/test_bpf.c
@@ -1761,9 +1761,9 @@ static int probe_filter_length(struct sock_filter *fp)
return len + 1;
}
-static struct sk_filter *generate_filter(int which, int *err)
+static struct bpf_prog *generate_filter(int which, int *err)
{
- struct sk_filter *fp;
+ struct bpf_prog *fp;
struct sock_fprog_kern fprog;
unsigned int flen = probe_filter_length(tests[which].u.insns);
__u8 test_type = tests[which].aux & TEST_TYPE_MASK;
@@ -1773,7 +1773,7 @@ static struct sk_filter *generate_filter(int which, int *err)
fprog.filter = tests[which].u.insns;
fprog.len = flen;
- *err = sk_unattached_filter_create(&fp, &fprog);
+ *err = bpf_prog_create(&fp, &fprog);
if (tests[which].aux & FLAG_EXPECTED_FAIL) {
if (*err == -EINVAL) {
pr_cont("PASS\n");
@@ -1798,7 +1798,7 @@ static struct sk_filter *generate_filter(int which, int *err)
break;
case INTERNAL:
- fp = kzalloc(sk_filter_size(flen), GFP_KERNEL);
+ fp = kzalloc(bpf_prog_size(flen), GFP_KERNEL);
if (fp == NULL) {
pr_cont("UNEXPECTED_FAIL no memory left\n");
*err = -ENOMEM;
@@ -1809,7 +1809,7 @@ static struct sk_filter *generate_filter(int which, int *err)
memcpy(fp->insnsi, tests[which].u.insns_int,
fp->len * sizeof(struct bpf_insn));
- sk_filter_select_runtime(fp);
+ bpf_prog_select_runtime(fp);
break;
}
@@ -1817,21 +1817,21 @@ static struct sk_filter *generate_filter(int which, int *err)
return fp;
}
-static void release_filter(struct sk_filter *fp, int which)
+static void release_filter(struct bpf_prog *fp, int which)
{
__u8 test_type = tests[which].aux & TEST_TYPE_MASK;
switch (test_type) {
case CLASSIC:
- sk_unattached_filter_destroy(fp);
+ bpf_prog_destroy(fp);
break;
case INTERNAL:
- sk_filter_free(fp);
+ bpf_prog_free(fp);
break;
}
}
-static int __run_one(const struct sk_filter *fp, const void *data,
+static int __run_one(const struct bpf_prog *fp, const void *data,
int runs, u64 *duration)
{
u64 start, finish;
@@ -1840,7 +1840,7 @@ static int __run_one(const struct sk_filter *fp, const void *data,
start = ktime_to_us(ktime_get());
for (i = 0; i < runs; i++)
- ret = SK_RUN_FILTER(fp, data);
+ ret = BPF_PROG_RUN(fp, data);
finish = ktime_to_us(ktime_get());
@@ -1850,7 +1850,7 @@ static int __run_one(const struct sk_filter *fp, const void *data,
return ret;
}
-static int run_one(const struct sk_filter *fp, struct bpf_test *test)
+static int run_one(const struct bpf_prog *fp, struct bpf_test *test)
{
int err_cnt = 0, i, runs = MAX_TESTRUNS;
@@ -1884,7 +1884,7 @@ static __init int test_bpf(void)
int i, err_cnt = 0, pass_cnt = 0;
for (i = 0; i < ARRAY_SIZE(tests); i++) {
- struct sk_filter *fp;
+ struct bpf_prog *fp;
int err;
pr_info("#%d %s ", i, tests[i].descr);
diff --git a/net/core/filter.c b/net/core/filter.c
index 6ac901613bee..d814b8a89d0f 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -810,8 +810,8 @@ int bpf_check_classic(const struct sock_filter *filter, unsigned int flen)
}
EXPORT_SYMBOL(bpf_check_classic);
-static int sk_store_orig_filter(struct sk_filter *fp,
- const struct sock_fprog *fprog)
+static int bpf_prog_store_orig_filter(struct bpf_prog *fp,
+ const struct sock_fprog *fprog)
{
unsigned int fsize = bpf_classic_proglen(fprog);
struct sock_fprog_kern *fkprog;
@@ -831,7 +831,7 @@ static int sk_store_orig_filter(struct sk_filter *fp,
return 0;
}
-static void sk_release_orig_filter(struct sk_filter *fp)
+static void bpf_release_orig_filter(struct bpf_prog *fp)
{
struct sock_fprog_kern *fprog = fp->orig_prog;
@@ -841,10 +841,16 @@ static void sk_release_orig_filter(struct sk_filter *fp)
}
}
+static void __bpf_prog_release(struct bpf_prog *prog)
+{
+ bpf_release_orig_filter(prog);
+ bpf_prog_free(prog);
+}
+
static void __sk_filter_release(struct sk_filter *fp)
{
- sk_release_orig_filter(fp);
- sk_filter_free(fp);
+ __bpf_prog_release(fp->prog);
+ kfree(fp);
}
/**
@@ -872,7 +878,7 @@ static void sk_filter_release(struct sk_filter *fp)
void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp)
{
- u32 filter_size = sk_filter_size(fp->len);
+ u32 filter_size = bpf_prog_size(fp->prog->len);
atomic_sub(filter_size, &sk->sk_omem_alloc);
sk_filter_release(fp);
@@ -883,7 +889,7 @@ void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp)
*/
bool sk_filter_charge(struct sock *sk, struct sk_filter *fp)
{
- u32 filter_size = sk_filter_size(fp->len);
+ u32 filter_size = bpf_prog_size(fp->prog->len);
/* same check as in sock_kmalloc() */
if (filter_size <= sysctl_optmem_max &&
@@ -895,10 +901,10 @@ bool sk_filter_charge(struct sock *sk, struct sk_filter *fp)
return false;
}
-static struct sk_filter *__sk_migrate_filter(struct sk_filter *fp)
+static struct bpf_prog *bpf_migrate_filter(struct bpf_prog *fp)
{
struct sock_filter *old_prog;
- struct sk_filter *old_fp;
+ struct bpf_prog *old_fp;
int err, new_len, old_len = fp->len;
/* We are free to overwrite insns et al right here as it
@@ -927,7 +933,7 @@ static struct sk_filter *__sk_migrate_filter(struct sk_filter *fp)
/* Expand fp for appending the new filter representation. */
old_fp = fp;
- fp = krealloc(old_fp, sk_filter_size(new_len), GFP_KERNEL);
+ fp = krealloc(old_fp, bpf_prog_size(new_len), GFP_KERNEL);
if (!fp) {
/* The old_fp is still around in case we couldn't
* allocate new memory, so uncharge on that one.
@@ -949,7 +955,7 @@ static struct sk_filter *__sk_migrate_filter(struct sk_filter *fp)
*/
goto out_err_free;
- sk_filter_select_runtime(fp);
+ bpf_prog_select_runtime(fp);
kfree(old_prog);
return fp;
@@ -957,11 +963,11 @@ static struct sk_filter *__sk_migrate_filter(struct sk_filter *fp)
out_err_free:
kfree(old_prog);
out_err:
- __sk_filter_release(fp);
+ __bpf_prog_release(fp);
return ERR_PTR(err);
}
-static struct sk_filter *__sk_prepare_filter(struct sk_filter *fp)
+static struct bpf_prog *bpf_prepare_filter(struct bpf_prog *fp)
{
int err;
@@ -970,7 +976,7 @@ static struct sk_filter *__sk_prepare_filter(struct sk_filter *fp)
err = bpf_check_classic(fp->insns, fp->len);
if (err) {
- __sk_filter_release(fp);
+ __bpf_prog_release(fp);
return ERR_PTR(err);
}
@@ -983,13 +989,13 @@ static struct sk_filter *__sk_prepare_filter(struct sk_filter *fp)
* internal BPF translation for the optimized interpreter.
*/
if (!fp->jited)
- fp = __sk_migrate_filter(fp);
+ fp = bpf_migrate_filter(fp);
return fp;
}
/**
- * sk_unattached_filter_create - create an unattached filter
+ * bpf_prog_create - create an unattached filter
* @pfp: the unattached filter that is created
* @fprog: the filter program
*
@@ -998,23 +1004,21 @@ static struct sk_filter *__sk_prepare_filter(struct sk_filter *fp)
* If an error occurs or there is insufficient memory for the filter
* a negative errno code is returned. On success the return is zero.
*/
-int sk_unattached_filter_create(struct sk_filter **pfp,
- struct sock_fprog_kern *fprog)
+int bpf_prog_create(struct bpf_prog **pfp, struct sock_fprog_kern *fprog)
{
unsigned int fsize = bpf_classic_proglen(fprog);
- struct sk_filter *fp;
+ struct bpf_prog *fp;
/* Make sure new filter is there and in the right amounts. */
if (fprog->filter == NULL)
return -EINVAL;
- fp = kmalloc(sk_filter_size(fprog->len), GFP_KERNEL);
+ fp = kmalloc(bpf_prog_size(fprog->len), GFP_KERNEL);
if (!fp)
return -ENOMEM;
memcpy(fp->insns, fprog->filter, fsize);
- atomic_set(&fp->refcnt, 1);
fp->len = fprog->len;
/* Since unattached filters are not copied back to user
* space through sk_get_filter(), we do not need to hold
@@ -1022,23 +1026,23 @@ int sk_unattached_filter_create(struct sk_filter **pfp,
*/
fp->orig_prog = NULL;
- /* __sk_prepare_filter() already takes care of freeing
+ /* bpf_prepare_filter() already takes care of freeing
* memory in case something goes wrong.
*/
- fp = __sk_prepare_filter(fp);
+ fp = bpf_prepare_filter(fp);
if (IS_ERR(fp))
return PTR_ERR(fp);
*pfp = fp;
return 0;
}
-EXPORT_SYMBOL_GPL(sk_unattached_filter_create);
+EXPORT_SYMBOL_GPL(bpf_prog_create);
-void sk_unattached_filter_destroy(struct sk_filter *fp)
+void bpf_prog_destroy(struct bpf_prog *fp)
{
- __sk_filter_release(fp);
+ __bpf_prog_release(fp);
}
-EXPORT_SYMBOL_GPL(sk_unattached_filter_destroy);
+EXPORT_SYMBOL_GPL(bpf_prog_destroy);
/**
* sk_attach_filter - attach a socket filter
@@ -1054,7 +1058,8 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
{
struct sk_filter *fp, *old_fp;
unsigned int fsize = bpf_classic_proglen(fprog);
- unsigned int sk_fsize = sk_filter_size(fprog->len);
+ unsigned int bpf_fsize = bpf_prog_size(fprog->len);
+ struct bpf_prog *prog;
int err;
if (sock_flag(sk, SOCK_FILTER_LOCKED))
@@ -1064,29 +1069,36 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
if (fprog->filter == NULL)
return -EINVAL;
- fp = kmalloc(sk_fsize, GFP_KERNEL);
- if (!fp)
+ prog = kmalloc(bpf_fsize, GFP_KERNEL);
+ if (!prog)
return -ENOMEM;
- if (copy_from_user(fp->insns, fprog->filter, fsize)) {
- kfree(fp);
+ if (copy_from_user(prog->insns, fprog->filter, fsize)) {
+ kfree(prog);
return -EFAULT;
}
- fp->len = fprog->len;
+ prog->len = fprog->len;
- err = sk_store_orig_filter(fp, fprog);
+ err = bpf_prog_store_orig_filter(prog, fprog);
if (err) {
- kfree(fp);
+ kfree(prog);
return -ENOMEM;
}
- /* __sk_prepare_filter() already takes care of freeing
+ /* bpf_prepare_filter() already takes care of freeing
* memory in case something goes wrong.
*/
- fp = __sk_prepare_filter(fp);
- if (IS_ERR(fp))
- return PTR_ERR(fp);
+ prog = bpf_prepare_filter(prog);
+ if (IS_ERR(prog))
+ return PTR_ERR(prog);
+
+ fp = kmalloc(sizeof(*fp), GFP_KERNEL);
+ if (!fp) {
+ __bpf_prog_release(prog);
+ return -ENOMEM;
+ }
+ fp->prog = prog;
atomic_set(&fp->refcnt, 0);
@@ -1142,7 +1154,7 @@ int sk_get_filter(struct sock *sk, struct sock_filter __user *ubuf,
/* We're copying the filter that has been originally attached,
* so no conversion/decode needed anymore.
*/
- fprog = filter->orig_prog;
+ fprog = filter->prog->orig_prog;
ret = fprog->len;
if (!len)
diff --git a/net/core/ptp_classifier.c b/net/core/ptp_classifier.c
index 12ab7b4be609..4eab4a94a59d 100644
--- a/net/core/ptp_classifier.c
+++ b/net/core/ptp_classifier.c
@@ -107,11 +107,11 @@
#include <linux/filter.h>
#include <linux/ptp_classify.h>
-static struct sk_filter *ptp_insns __read_mostly;
+static struct bpf_prog *ptp_insns __read_mostly;
unsigned int ptp_classify_raw(const struct sk_buff *skb)
{
- return SK_RUN_FILTER(ptp_insns, skb);
+ return BPF_PROG_RUN(ptp_insns, skb);
}
EXPORT_SYMBOL_GPL(ptp_classify_raw);
@@ -189,5 +189,5 @@ void __init ptp_classifier_init(void)
.len = ARRAY_SIZE(ptp_filter), .filter = ptp_filter,
};
- BUG_ON(sk_unattached_filter_create(&ptp_insns, &ptp_prog));
+ BUG_ON(bpf_prog_create(&ptp_insns, &ptp_prog));
}
diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c
index 57d922320c59..ad704c757bb4 100644
--- a/net/core/sock_diag.c
+++ b/net/core/sock_diag.c
@@ -68,7 +68,7 @@ int sock_diag_put_filterinfo(bool may_report_filterinfo, struct sock *sk,
if (!filter)
goto out;
- fprog = filter->orig_prog;
+ fprog = filter->prog->orig_prog;
flen = bpf_classic_proglen(fprog);
attr = nla_reserve(skb, attrtype, flen);
diff --git a/net/netfilter/xt_bpf.c b/net/netfilter/xt_bpf.c
index bbffdbdaf603..dffee9d47ec4 100644
--- a/net/netfilter/xt_bpf.c
+++ b/net/netfilter/xt_bpf.c
@@ -28,7 +28,7 @@ static int bpf_mt_check(const struct xt_mtchk_param *par)
program.len = info->bpf_program_num_elem;
program.filter = info->bpf_program;
- if (sk_unattached_filter_create(&info->filter, &program)) {
+ if (bpf_prog_create(&info->filter, &program)) {
pr_info("bpf: check failed: parse error\n");
return -EINVAL;
}
@@ -40,13 +40,13 @@ static bool bpf_mt(const struct sk_buff *skb, struct xt_action_param *par)
{
const struct xt_bpf_info *info = par->matchinfo;
- return SK_RUN_FILTER(info->filter, skb);
+ return BPF_PROG_RUN(info->filter, skb);
}
static void bpf_mt_destroy(const struct xt_mtdtor_param *par)
{
const struct xt_bpf_info *info = par->matchinfo;
- sk_unattached_filter_destroy(info->filter);
+ bpf_prog_destroy(info->filter);
}
static struct xt_match bpf_mt_reg __read_mostly = {
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c
index 13f64df2c710..0e30d58149da 100644
--- a/net/sched/cls_bpf.c
+++ b/net/sched/cls_bpf.c
@@ -30,7 +30,7 @@ struct cls_bpf_head {
};
struct cls_bpf_prog {
- struct sk_filter *filter;
+ struct bpf_prog *filter;
struct sock_filter *bpf_ops;
struct tcf_exts exts;
struct tcf_result res;
@@ -54,7 +54,7 @@ static int cls_bpf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
int ret;
list_for_each_entry(prog, &head->plist, link) {
- int filter_res = SK_RUN_FILTER(prog->filter, skb);
+ int filter_res = BPF_PROG_RUN(prog->filter, skb);
if (filter_res == 0)
continue;
@@ -92,7 +92,7 @@ static void cls_bpf_delete_prog(struct tcf_proto *tp, struct cls_bpf_prog *prog)
tcf_unbind_filter(tp, &prog->res);
tcf_exts_destroy(tp, &prog->exts);
- sk_unattached_filter_destroy(prog->filter);
+ bpf_prog_destroy(prog->filter);
kfree(prog->bpf_ops);
kfree(prog);
@@ -161,7 +161,7 @@ static int cls_bpf_modify_existing(struct net *net, struct tcf_proto *tp,
struct sock_filter *bpf_ops, *bpf_old;
struct tcf_exts exts;
struct sock_fprog_kern tmp;
- struct sk_filter *fp, *fp_old;
+ struct bpf_prog *fp, *fp_old;
u16 bpf_size, bpf_len;
u32 classid;
int ret;
@@ -193,7 +193,7 @@ static int cls_bpf_modify_existing(struct net *net, struct tcf_proto *tp,
tmp.len = bpf_len;
tmp.filter = bpf_ops;
- ret = sk_unattached_filter_create(&fp, &tmp);
+ ret = bpf_prog_create(&fp, &tmp);
if (ret)
goto errout_free;
@@ -211,7 +211,7 @@ static int cls_bpf_modify_existing(struct net *net, struct tcf_proto *tp,
tcf_exts_change(tp, &prog->exts, &exts);
if (fp_old)
- sk_unattached_filter_destroy(fp_old);
+ bpf_prog_destroy(fp_old);
if (bpf_old)
kfree(bpf_old);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v4 net-next 5/5] net: filter: split 'struct sk_filter' into socket and bpf parts
2014-07-31 3:34 ` [PATCH v4 net-next 5/5] net: filter: split 'struct sk_filter' into socket and bpf parts Alexei Starovoitov
@ 2014-07-31 19:40 ` Pablo Neira Ayuso
2014-07-31 21:02 ` Alexei Starovoitov
0 siblings, 1 reply; 14+ messages in thread
From: Pablo Neira Ayuso @ 2014-07-31 19:40 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: David S. Miller, Daniel Borkmann, Willem de Bruijn, Kees Cook,
netdev, linux-kernel, netfilter-devel
On Wed, Jul 30, 2014 at 08:34:16PM -0700, Alexei Starovoitov wrote:
> clean up names related to socket filtering and bpf in the following way:
> - everything that deals with sockets keeps 'sk_*' prefix
> - everything that is pure BPF is changed to 'bpf_*' prefix
>
> split 'struct sk_filter' into
> struct sk_filter {
> atomic_t refcnt;
> struct rcu_head rcu;
> struct bpf_prog *prog;
> };
I think you can use 'struct bpf_prog prog' instead so the entire
sk_filter remains in the same memory blob (as it is before this
patch).
You can add an inline function to retrieve the bpg prog from the
filter:
static inline struct bpf_prog *sk_filter_bpf(struct sk_filter *)
and use it whenever possible to fetch the bpf program. I'm suggesting
this because we can use the zero array size in the socket filtering
abstraction later on, if the function above is used, this just needs
one line in that function to be updated to fetch the program from the
placeholder.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v4 net-next 5/5] net: filter: split 'struct sk_filter' into socket and bpf parts
2014-07-31 19:40 ` Pablo Neira Ayuso
@ 2014-07-31 21:02 ` Alexei Starovoitov
2014-08-01 16:06 ` Pablo Neira Ayuso
0 siblings, 1 reply; 14+ messages in thread
From: Alexei Starovoitov @ 2014-07-31 21:02 UTC (permalink / raw)
To: Pablo Neira Ayuso
Cc: David S. Miller, Daniel Borkmann, Willem de Bruijn, Kees Cook,
Network Development, LKML, netfilter-devel
On Thu, Jul 31, 2014 at 12:40 PM, Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> On Wed, Jul 30, 2014 at 08:34:16PM -0700, Alexei Starovoitov wrote:
>> clean up names related to socket filtering and bpf in the following way:
>> - everything that deals with sockets keeps 'sk_*' prefix
>> - everything that is pure BPF is changed to 'bpf_*' prefix
>>
>> split 'struct sk_filter' into
>> struct sk_filter {
>> atomic_t refcnt;
>> struct rcu_head rcu;
>> struct bpf_prog *prog;
>> };
>
> I think you can use 'struct bpf_prog prog' instead so the entire
> sk_filter remains in the same memory blob (as it is before this
> patch).
>
> You can add an inline function to retrieve the bpg prog from the
> filter:
>
> static inline struct bpf_prog *sk_filter_bpf(struct sk_filter *)
>
> and use it whenever possible to fetch the bpf program. I'm suggesting
> this because we can use the zero array size in the socket filtering
> abstraction later on, if the function above is used, this just needs
> one line in that function to be updated to fetch the program from the
> placeholder.
correct. It would speed up SK_RUN_FILTER macro a little and I've
considered it, but decided to go with the pointer for two reasons:
1.In sk_attach_filter() the bpf_prog is allocated, then reallocated
as part of bpf_prepare_filter(). My patch #1 cleans up that part to
avoid 'struct sock *' dependency, so all bpf_* functions work
purely with bpf_prog... If bpf_prog is embedded inside sk_filter,
bpf_prepare_filter would need to have a callback to reallocate
the container struct and pass this callback through the chain
of calls, which is ugly.
2. having it as a pointer helps nft in the long run, since whole of
bpf_prog doesn't stay around inside sk_filter when it's not used.
So I think embedding pointer was a cleaner solution.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v4 net-next 5/5] net: filter: split 'struct sk_filter' into socket and bpf parts
2014-07-31 21:02 ` Alexei Starovoitov
@ 2014-08-01 16:06 ` Pablo Neira Ayuso
2014-08-01 16:50 ` Alexei Starovoitov
0 siblings, 1 reply; 14+ messages in thread
From: Pablo Neira Ayuso @ 2014-08-01 16:06 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: David S. Miller, Daniel Borkmann, Willem de Bruijn, Kees Cook,
Network Development, LKML, netfilter-devel
On Thu, Jul 31, 2014 at 02:02:19PM -0700, Alexei Starovoitov wrote:
> On Thu, Jul 31, 2014 at 12:40 PM, Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> > On Wed, Jul 30, 2014 at 08:34:16PM -0700, Alexei Starovoitov wrote:
> >> clean up names related to socket filtering and bpf in the following way:
> >> - everything that deals with sockets keeps 'sk_*' prefix
> >> - everything that is pure BPF is changed to 'bpf_*' prefix
> >>
> >> split 'struct sk_filter' into
> >> struct sk_filter {
> >> atomic_t refcnt;
> >> struct rcu_head rcu;
> >> struct bpf_prog *prog;
> >> };
> >
> > I think you can use 'struct bpf_prog prog' instead so the entire
> > sk_filter remains in the same memory blob (as it is before this
> > patch).
> >
> > You can add an inline function to retrieve the bpg prog from the
> > filter:
> >
> > static inline struct bpf_prog *sk_filter_bpf(struct sk_filter *)
> >
> > and use it whenever possible to fetch the bpf program. I'm suggesting
> > this because we can use the zero array size in the socket filtering
> > abstraction later on, if the function above is used, this just needs
> > one line in that function to be updated to fetch the program from the
> > placeholder.
>
> correct. It would speed up SK_RUN_FILTER macro a little and I've
> considered it, but decided to go with the pointer for two reasons:
> 1.In sk_attach_filter() the bpf_prog is allocated, then reallocated
> as part of bpf_prepare_filter(). My patch #1 cleans up that part to
> avoid 'struct sock *' dependency, so all bpf_* functions work
> purely with bpf_prog... If bpf_prog is embedded inside sk_filter,
> bpf_prepare_filter would need to have a callback to reallocate
> the container struct and pass this callback through the chain
> of calls, which is ugly
I think you can allocate the sk_filter once you get the final bpf
program, then you can memcpy() it. This adds some extra overhead in
the sk_attach_filter(), but that path is executed from user context
and it's also a rare operation (only once to attach the filter). It's
still not going to be a beauty, but IMO it's worth to focus on getting
that little speed up in the packet path at the cost of adding some
overhead on the socket attach path.
> 2. having it as a pointer helps nft in the long run, since whole of
> bpf_prog doesn't stay around inside sk_filter when it's not used.
If you put into place the inline wrapper function that I'm proposing
above and you use it instead of fp->bpf_prog, I think there should be
not interference:
static inline struct bpf_prog *sk_filter_bpf(struct sk_filter *sk)
{
- return &sk->bpf_prog;
+ return (struct bpf_prog *)sk->data;
}
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v4 net-next 5/5] net: filter: split 'struct sk_filter' into socket and bpf parts
2014-08-01 16:06 ` Pablo Neira Ayuso
@ 2014-08-01 16:50 ` Alexei Starovoitov
2014-08-01 19:03 ` Pablo Neira Ayuso
0 siblings, 1 reply; 14+ messages in thread
From: Alexei Starovoitov @ 2014-08-01 16:50 UTC (permalink / raw)
To: Pablo Neira Ayuso
Cc: David S. Miller, Daniel Borkmann, Willem de Bruijn, Kees Cook,
Network Development, LKML, netfilter-devel
On Fri, Aug 1, 2014 at 9:06 AM, Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> On Thu, Jul 31, 2014 at 02:02:19PM -0700, Alexei Starovoitov wrote:
>> On Thu, Jul 31, 2014 at 12:40 PM, Pablo Neira Ayuso <pablo@netfilter.org> wrote:
>> > On Wed, Jul 30, 2014 at 08:34:16PM -0700, Alexei Starovoitov wrote:
>> >> clean up names related to socket filtering and bpf in the following way:
>> >> - everything that deals with sockets keeps 'sk_*' prefix
>> >> - everything that is pure BPF is changed to 'bpf_*' prefix
>> >>
>> >> split 'struct sk_filter' into
>> >> struct sk_filter {
>> >> atomic_t refcnt;
>> >> struct rcu_head rcu;
>> >> struct bpf_prog *prog;
>> >> };
>> >
>> > I think you can use 'struct bpf_prog prog' instead so the entire
>> > sk_filter remains in the same memory blob (as it is before this
>> > patch).
>> >
>> > You can add an inline function to retrieve the bpg prog from the
>> > filter:
>> >
>> > static inline struct bpf_prog *sk_filter_bpf(struct sk_filter *)
>> >
>> > and use it whenever possible to fetch the bpf program. I'm suggesting
>> > this because we can use the zero array size in the socket filtering
>> > abstraction later on, if the function above is used, this just needs
>> > one line in that function to be updated to fetch the program from the
>> > placeholder.
>>
>> correct. It would speed up SK_RUN_FILTER macro a little and I've
>> considered it, but decided to go with the pointer for two reasons:
>> 1.In sk_attach_filter() the bpf_prog is allocated, then reallocated
>> as part of bpf_prepare_filter(). My patch #1 cleans up that part to
>> avoid 'struct sock *' dependency, so all bpf_* functions work
>> purely with bpf_prog... If bpf_prog is embedded inside sk_filter,
>> bpf_prepare_filter would need to have a callback to reallocate
>> the container struct and pass this callback through the chain
>> of calls, which is ugly
>
> I think you can allocate the sk_filter once you get the final bpf
> program, then you can memcpy() it. This adds some extra overhead in
> the sk_attach_filter(), but that path is executed from user context
> and it's also a rare operation (only once to attach the filter). It's
> still not going to be a beauty, but IMO it's worth to focus on getting
> that little speed up in the packet path at the cost of adding some
> overhead on the socket attach path.
memcpy of 'bpf_prog' is not just 'not a beauty', it won't work, since
bpf_prog is freed via work_queue due to JIT. See bpf_jit_free()
There are few other ways I could think of embedding bpf_prog inside
sk_filter: 1. have a release callback, 2. extra field inside bpf_prog
that will tell outer size of the container (so that all kfree(bpf_prog*)
can adjust the pointer before freeing). 3. extra field which is direct
pointer to the outer container, so that kfree(bpf_prog*) can use it
instead of freeing the bpf_prog itself.
In all cases it means hacking jit compilers for all architectures
in a very ugly way.
Say, we pick #3 (which is the least ugly), see how
kfree(fp) will change to
kfree(fp->pointer_to_outer_container).
it will be not obvious at all to the reader that bpf_prog itself will be
freed by such kfree()... so we'd need to add nasty comments
everywhere...
imo one extra load of fp->prog in critical path of SK_RUN_FILTER
is not worth this mess.
>> 2. having it as a pointer helps nft in the long run, since whole of
>> bpf_prog doesn't stay around inside sk_filter when it's not used.
>
> If you put into place the inline wrapper function that I'm proposing
> above and you use it instead of fp->bpf_prog, I think there should be
> not interference:
>
> static inline struct bpf_prog *sk_filter_bpf(struct sk_filter *sk)
> {
> - return &sk->bpf_prog;
> + return (struct bpf_prog *)sk->data;
> }
This is not pretty either, since we'd need to worry that alignment
of sk->data field must match alignment of bpf_prog. Probably can
make it 'long data[0]'... all of these just feels wrong to avoid
single load in SK_RUN_FILTER().
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v4 net-next 5/5] net: filter: split 'struct sk_filter' into socket and bpf parts
2014-08-01 16:50 ` Alexei Starovoitov
@ 2014-08-01 19:03 ` Pablo Neira Ayuso
2014-08-01 19:12 ` Alexei Starovoitov
0 siblings, 1 reply; 14+ messages in thread
From: Pablo Neira Ayuso @ 2014-08-01 19:03 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: David S. Miller, Daniel Borkmann, Willem de Bruijn, Kees Cook,
Network Development, LKML, netfilter-devel
On Fri, Aug 01, 2014 at 09:50:31AM -0700, Alexei Starovoitov wrote:
> On Fri, Aug 1, 2014 at 9:06 AM, Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> > On Thu, Jul 31, 2014 at 02:02:19PM -0700, Alexei Starovoitov wrote:
> >> On Thu, Jul 31, 2014 at 12:40 PM, Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> >> > On Wed, Jul 30, 2014 at 08:34:16PM -0700, Alexei Starovoitov wrote:
> >> >> clean up names related to socket filtering and bpf in the following way:
> >> >> - everything that deals with sockets keeps 'sk_*' prefix
> >> >> - everything that is pure BPF is changed to 'bpf_*' prefix
> >> >>
> >> >> split 'struct sk_filter' into
> >> >> struct sk_filter {
> >> >> atomic_t refcnt;
> >> >> struct rcu_head rcu;
> >> >> struct bpf_prog *prog;
> >> >> };
> >> >
> >> > I think you can use 'struct bpf_prog prog' instead so the entire
> >> > sk_filter remains in the same memory blob (as it is before this
> >> > patch).
> >> >
> >> > You can add an inline function to retrieve the bpg prog from the
> >> > filter:
> >> >
> >> > static inline struct bpf_prog *sk_filter_bpf(struct sk_filter *)
> >> >
> >> > and use it whenever possible to fetch the bpf program. I'm suggesting
> >> > this because we can use the zero array size in the socket filtering
> >> > abstraction later on, if the function above is used, this just needs
> >> > one line in that function to be updated to fetch the program from the
> >> > placeholder.
> >>
> >> correct. It would speed up SK_RUN_FILTER macro a little and I've
> >> considered it, but decided to go with the pointer for two reasons:
> >> 1.In sk_attach_filter() the bpf_prog is allocated, then reallocated
> >> as part of bpf_prepare_filter(). My patch #1 cleans up that part to
> >> avoid 'struct sock *' dependency, so all bpf_* functions work
> >> purely with bpf_prog... If bpf_prog is embedded inside sk_filter,
> >> bpf_prepare_filter would need to have a callback to reallocate
> >> the container struct and pass this callback through the chain
> >> of calls, which is ugly
> >
> > I think you can allocate the sk_filter once you get the final bpf
> > program, then you can memcpy() it. This adds some extra overhead in
> > the sk_attach_filter(), but that path is executed from user context
> > and it's also a rare operation (only once to attach the filter). It's
> > still not going to be a beauty, but IMO it's worth to focus on getting
> > that little speed up in the packet path at the cost of adding some
> > overhead on the socket attach path.
>
> memcpy of 'bpf_prog' is not just 'not a beauty', it won't work, since
> bpf_prog is freed via work_queue due to JIT. See bpf_jit_free()
[...]
I see, in this patch you renamed sk_filter to bpf_prog in
bpf_jit_free() so no access to sk_filter anymore and alignment needs a
closer look.
OK... let's stick to the struct bpf_prog pointer.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v4 net-next 5/5] net: filter: split 'struct sk_filter' into socket and bpf parts
2014-08-01 19:03 ` Pablo Neira Ayuso
@ 2014-08-01 19:12 ` Alexei Starovoitov
2014-08-02 22:10 ` David Miller
0 siblings, 1 reply; 14+ messages in thread
From: Alexei Starovoitov @ 2014-08-01 19:12 UTC (permalink / raw)
To: Pablo Neira Ayuso
Cc: David S. Miller, Daniel Borkmann, Willem de Bruijn, Kees Cook,
Network Development, LKML, netfilter-devel
On Fri, Aug 1, 2014 at 12:03 PM, Pablo Neira Ayuso <pablo@netfilter.org> wrote:
>> > I think you can allocate the sk_filter once you get the final bpf
>> > program, then you can memcpy() it. This adds some extra overhead in
>> > the sk_attach_filter(), but that path is executed from user context
>> > and it's also a rare operation (only once to attach the filter). It's
>> > still not going to be a beauty, but IMO it's worth to focus on getting
>> > that little speed up in the packet path at the cost of adding some
>> > overhead on the socket attach path.
>>
>> memcpy of 'bpf_prog' is not just 'not a beauty', it won't work, since
>> bpf_prog is freed via work_queue due to JIT. See bpf_jit_free()
> [...]
>
> I see, in this patch you renamed sk_filter to bpf_prog in
> bpf_jit_free() so no access to sk_filter anymore and alignment needs a
> closer look.
>
> OK... let's stick to the struct bpf_prog pointer.
great. Once nft comes along we can always revisit this bit.
Dave, this patch has trivial conflict with Daniel's
("team: fix releasing uninitialized pointer to BPF prog") fix.
Let me know if you want me to respin the series or you'll patch up
the conflict yourself.
Thanks
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v4 net-next 0/5] net: filter: split sk_filter into socket and bpf, cleanup names
2014-07-31 3:34 [PATCH v4 net-next 0/5] net: filter: split sk_filter into socket and bpf, cleanup names Alexei Starovoitov
` (4 preceding siblings ...)
2014-07-31 3:34 ` [PATCH v4 net-next 5/5] net: filter: split 'struct sk_filter' into socket and bpf parts Alexei Starovoitov
@ 2014-08-02 22:09 ` David Miller
5 siblings, 0 replies; 14+ messages in thread
From: David Miller @ 2014-08-02 22:09 UTC (permalink / raw)
To: ast
Cc: dborkman, willemb, pablo, keescook, netdev, linux-kernel,
netfilter-devel
From: Alexei Starovoitov <ast@plumgrid.com>
Date: Wed, 30 Jul 2014 20:34:11 -0700
> The main goal of the series is to split 'struct sk_filter' into socket and
> bpf parts and cleanup names in the following way:
> - everything that deals with sockets keeps 'sk_*' prefix
> - everything that is pure BPF is changed to 'bpf_*' prefix
>
> split 'struct sk_filter' into
> struct sk_filter {
> atomic_t refcnt;
> struct rcu_head rcu;
> struct bpf_prog *prog;
> };
> and
> struct bpf_prog {
> u32 jited:1,
> len:31;
> struct sock_fprog_kern *orig_prog;
> unsigned int (*bpf_func)(const struct sk_buff *skb,
> const struct bpf_insn *filter);
> union {
> struct sock_filter insns[0];
> struct bpf_insn insnsi[0];
> struct work_struct work;
> };
> };
> so that 'struct bpf_prog' can be used independent of sockets and cleans up
> 'unattached' bpf use cases:
> isdn, ppp, team, seccomp, ptp, xt_bpf, cls_bpf, test_bpf
> which don't need refcnt/rcu fields.
>
> It's a follow up to the rcu cleanup started by Pablo in
> commit 34c5bd66e5 ("net: filter: don't release unattached filter through call_rcu()")
>
> Patch 1 - cleans up socket memory charging and makes it possible for functions
> sk(bpf)_migrate_filter(), sk(bpf)_prepare_filter() to be socket independent
> Patches 2-4 - trivial renames
> Patch 5 - sk_filter split and renames of related sk_*() functions
Series applied, thanks Alexei.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v4 net-next 5/5] net: filter: split 'struct sk_filter' into socket and bpf parts
2014-08-01 19:12 ` Alexei Starovoitov
@ 2014-08-02 22:10 ` David Miller
0 siblings, 0 replies; 14+ messages in thread
From: David Miller @ 2014-08-02 22:10 UTC (permalink / raw)
To: ast
Cc: pablo, dborkman, willemb, keescook, netdev, linux-kernel,
netfilter-devel
From: Alexei Starovoitov <ast@plumgrid.com>
Date: Fri, 1 Aug 2014 12:12:36 -0700
> Dave, this patch has trivial conflict with Daniel's
> ("team: fix releasing uninitialized pointer to BPF prog") fix.
> Let me know if you want me to respin the series or you'll patch up
> the conflict yourself.
I took care of this, it was easy to resolve.
Thanks.
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2014-08-02 22:10 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-07-31 3:34 [PATCH v4 net-next 0/5] net: filter: split sk_filter into socket and bpf, cleanup names Alexei Starovoitov
2014-07-31 3:34 ` [PATCH v4 net-next 1/5] net: filter: simplify socket charging Alexei Starovoitov
2014-07-31 3:34 ` [PATCH v4 net-next 2/5] net: filter: rename sk_filter_proglen -> bpf_classic_proglen Alexei Starovoitov
2014-07-31 3:34 ` [PATCH v4 net-next 3/5] net: filter: rename sk_chk_filter() -> bpf_check_classic() Alexei Starovoitov
2014-07-31 3:34 ` [PATCH v4 net-next 4/5] net: filter: rename sk_convert_filter() -> bpf_convert_filter() Alexei Starovoitov
2014-07-31 3:34 ` [PATCH v4 net-next 5/5] net: filter: split 'struct sk_filter' into socket and bpf parts Alexei Starovoitov
2014-07-31 19:40 ` Pablo Neira Ayuso
2014-07-31 21:02 ` Alexei Starovoitov
2014-08-01 16:06 ` Pablo Neira Ayuso
2014-08-01 16:50 ` Alexei Starovoitov
2014-08-01 19:03 ` Pablo Neira Ayuso
2014-08-01 19:12 ` Alexei Starovoitov
2014-08-02 22:10 ` David Miller
2014-08-02 22:09 ` [PATCH v4 net-next 0/5] net: filter: split sk_filter into socket and bpf, cleanup names David Miller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).