From: Pablo Neira Ayuso <pablo@netfilter.org>
To: netfilter-devel@vger.kernel.org
Cc: davem@davemloft.net, netdev@vger.kernel.org, kaber@trash.net
Subject: [PATCH RFC 2/9] net: filter: account filter length in bytes
Date: Tue, 11 Mar 2014 10:19:13 +0100 [thread overview]
Message-ID: <1394529560-3490-3-git-send-email-pablo@netfilter.org> (raw)
In-Reply-To: <1394529560-3490-1-git-send-email-pablo@netfilter.org>
This patch converts the len field in the struct sock_filter structure
from length in filter lines to bytes. I have added the new function
sk_bpf_flen() which allows you to obtain the filter in number of
blocks (which is what you usually need to iterate over a BPF filter).
The corresponding BPF jit implementation has been also adjusted.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
arch/arm/net/bpf_jit_32.c | 19 ++++++++++---------
arch/powerpc/net/bpf_jit_comp.c | 4 ++--
arch/s390/net/bpf_jit_comp.c | 10 +++++-----
arch/sparc/net/bpf_jit_comp.c | 2 +-
arch/x86/net/bpf_jit_comp.c | 2 +-
include/linux/filter.h | 10 ++++------
include/net/sock.h | 4 ++--
net/core/filter.c | 22 +++++++++++++++-------
net/core/sock_diag.c | 4 ++--
9 files changed, 42 insertions(+), 35 deletions(-)
diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
index 65bd347..844e97b 100644
--- a/arch/arm/net/bpf_jit_32.c
+++ b/arch/arm/net/bpf_jit_32.c
@@ -135,7 +135,7 @@ static u16 saved_regs(struct jit_ctx *ctx)
{
u16 ret = 0;
- if ((ctx->skf->len > 1) ||
+ if ((sk_bpf_flen(ctx->skf) > 1) ||
(ctx->skf->insns[0].code == BPF_S_RET_A))
ret |= 1 << r_A;
@@ -283,7 +283,7 @@ static u16 imm_offset(u32 k, struct jit_ctx *ctx)
ctx->imms[i] = k;
/* constants go just after the epilogue */
- offset = ctx->offsets[ctx->skf->len];
+ offset = ctx->offsets[sk_bpf_flen(ctx->skf)];
offset += ctx->prologue_bytes;
offset += ctx->epilogue_bytes;
offset += i * 4;
@@ -423,7 +423,7 @@ static inline void emit_err_ret(u8 cond, struct jit_ctx *ctx)
emit(ARM_MOV_R(ARM_R0, ARM_R0), ctx);
} else {
_emit(cond, ARM_MOV_I(ARM_R0, 0), ctx);
- _emit(cond, ARM_B(b_imm(ctx->skf->len, ctx)), ctx);
+ _emit(cond, ARM_B(b_imm(sk_bpf_flen(ctx->skf), ctx)), ctx);
}
}
@@ -476,10 +476,10 @@ static int build_body(struct jit_ctx *ctx)
const struct sk_filter *prog = ctx->skf;
const struct sock_filter *inst;
unsigned i, load_order, off, condt;
- int imm12;
+ int imm12, flen = sk_bpf_flen(ctx->skf);
u32 k;
- for (i = 0; i < prog->len; i++) {
+ for (i = 0; i < flen; i++) {
inst = &(prog->insns[i]);
/* K as an immediate value operand */
k = inst->k;
@@ -773,8 +773,8 @@ cmp_x:
ctx->ret0_fp_idx = i;
emit_mov_i(ARM_R0, k, ctx);
b_epilogue:
- if (i != ctx->skf->len - 1)
- emit(ARM_B(b_imm(prog->len, ctx)), ctx);
+ if (i != flen - 1)
+ emit(ARM_B(b_imm(flen, ctx)), ctx);
break;
case BPF_S_MISC_TAX:
/* X = A */
@@ -867,6 +867,7 @@ void bpf_jit_compile(struct sk_filter *fp)
struct jit_ctx ctx;
unsigned tmp_idx;
unsigned alloc_size;
+ int flen = sk_bpf_flen(fp);
if (!bpf_jit_enable)
return;
@@ -875,7 +876,7 @@ void bpf_jit_compile(struct sk_filter *fp)
ctx.skf = fp;
ctx.ret0_fp_idx = -1;
- ctx.offsets = kzalloc(4 * (ctx.skf->len + 1), GFP_KERNEL);
+ ctx.offsets = kzalloc(4 * (flen + 1), GFP_KERNEL);
if (ctx.offsets == NULL)
return;
@@ -922,7 +923,7 @@ void bpf_jit_compile(struct sk_filter *fp)
if (bpf_jit_enable > 1)
/* there are 2 passes here */
- bpf_jit_dump(fp->len, alloc_size, 2, ctx.target);
+ bpf_jit_dump(flen, alloc_size, 2, ctx.target);
fp->run_filter = (void *)ctx.target;
out:
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index 6491d72..a4d8db3 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -134,7 +134,7 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
unsigned int *addrs)
{
const struct sock_filter *filter = fp->insns;
- int flen = fp->len;
+ int flen = sk_bpf_flen(fp);
u8 *func;
unsigned int true_cond;
int i;
@@ -581,7 +581,7 @@ void bpf_jit_compile(struct sk_filter *fp)
unsigned int *addrs;
struct codegen_context cgctx;
int pass;
- int flen = fp->len;
+ int flen = sk_bpf_flen(fp);
if (!bpf_jit_enable)
return;
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
index 23089df..54906d9 100644
--- a/arch/s390/net/bpf_jit_comp.c
+++ b/arch/s390/net/bpf_jit_comp.c
@@ -826,11 +826,11 @@ void bpf_jit_compile(struct sk_filter *fp)
unsigned long size, prg_len, lit_len;
struct bpf_jit jit, cjit;
unsigned int *addrs;
- int pass, i;
+ int pass, i, flen = sk_bpf_flen(fp);
if (!bpf_jit_enable)
return;
- addrs = kcalloc(fp->len, sizeof(*addrs), GFP_KERNEL);
+ addrs = kcalloc(flen, sizeof(*addrs), GFP_KERNEL);
if (addrs == NULL)
return;
memset(&jit, 0, sizeof(cjit));
@@ -842,9 +842,9 @@ void bpf_jit_compile(struct sk_filter *fp)
bpf_jit_prologue(&jit);
bpf_jit_noleaks(&jit, fp->insns);
- for (i = 0; i < fp->len; i++) {
+ for (i = 0; i < flen; i++) {
if (bpf_jit_insn(&jit, fp->insns + i, addrs, i,
- i == fp->len - 1))
+ i == len - 1))
goto out;
}
bpf_jit_epilogue(&jit);
@@ -870,7 +870,7 @@ void bpf_jit_compile(struct sk_filter *fp)
cjit = jit;
}
if (bpf_jit_enable > 1) {
- bpf_jit_dump(fp->len, jit.end - jit.start, pass, jit.start);
+ bpf_jit_dump(flen, jit.end - jit.start, pass, jit.start);
if (jit.start)
print_fn_code(jit.start, jit.mid - jit.start);
}
diff --git a/arch/sparc/net/bpf_jit_comp.c b/arch/sparc/net/bpf_jit_comp.c
index ee1cd30..15e6b00 100644
--- a/arch/sparc/net/bpf_jit_comp.c
+++ b/arch/sparc/net/bpf_jit_comp.c
@@ -359,7 +359,7 @@ void bpf_jit_compile(struct sk_filter *fp)
unsigned int cleanup_addr, proglen, oldproglen = 0;
u32 temp[8], *prog, *func, seen = 0, pass;
const struct sock_filter *filter = fp->insns;
- int i, flen = fp->len, pc_ret0 = -1;
+ int i, flen = sk_bpf_flen(fp), pc_ret0 = -1;
unsigned int *addrs;
void *image;
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index bfadd14..81bf69a 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -193,7 +193,7 @@ void bpf_jit_compile(struct sk_filter *fp)
unsigned int cleanup_addr; /* epilogue code offset */
unsigned int *addrs;
const struct sock_filter *filter = fp->insns;
- int flen = fp->len;
+ int flen = sk_bpf_flen(fp);
if (!bpf_jit_enable)
return;
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 6c5d597..ab37714 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -22,10 +22,9 @@ struct compat_sock_fprog {
struct sk_buff;
struct sock;
-struct sk_filter
-{
+struct sk_filter {
atomic_t refcnt;
- unsigned int len; /* Number of filter blocks */
+ unsigned int size; /* filter bytecode size in bytes */
struct rcu_head rcu;
unsigned int (*run_filter)(const struct sk_buff *skb,
const struct sock_filter *filter);
@@ -35,10 +34,9 @@ struct sk_filter
};
};
-static inline unsigned int sk_filter_size(unsigned int proglen)
+static inline unsigned int sk_bpf_flen(struct sk_filter *filter)
{
- return max(sizeof(struct sk_filter),
- offsetof(struct sk_filter, insns[proglen]));
+ return filter->size / sizeof(struct sock_filter);
}
extern int sk_filter(struct sock *sk, struct sk_buff *skb);
diff --git a/include/net/sock.h b/include/net/sock.h
index 5c3f7c3..7b9723c 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1633,14 +1633,14 @@ static inline void sk_filter_release(struct sk_filter *fp)
static inline void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp)
{
- atomic_sub(sk_filter_size(fp->len), &sk->sk_omem_alloc);
+ atomic_sub(fp->size, &sk->sk_omem_alloc);
sk_filter_release(fp);
}
static inline 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_add(fp->size, &sk->sk_omem_alloc);
}
/*
diff --git a/net/core/filter.c b/net/core/filter.c
index 0f63e67..3ea0e7f 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -647,7 +647,7 @@ static int __sk_prepare_filter(struct sk_filter *fp)
fp->run_filter = sk_run_filter;
- err = sk_chk_filter(fp->insns, fp->len);
+ err = sk_chk_filter(fp->insns, sk_bpf_flen(fp));
if (err)
return err;
@@ -655,6 +655,12 @@ static int __sk_prepare_filter(struct sk_filter *fp)
return 0;
}
+static unsigned int sk_filter_size(unsigned int proglen)
+{
+ return max(sizeof(struct sk_filter),
+ offsetof(struct sk_filter, insns[proglen]));
+}
+
/**
* sk_unattached_filter_create - create an unattached filter
* @fprog: the filter program
@@ -682,7 +688,7 @@ int sk_unattached_filter_create(struct sk_filter **pfp,
memcpy(fp->insns, fprog->filter, fsize);
atomic_set(&fp->refcnt, 1);
- fp->len = fprog->len;
+ fp->size = fsize;
err = __sk_prepare_filter(fp);
if (err)
@@ -735,7 +741,7 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
}
atomic_set(&fp->refcnt, 1);
- fp->len = fprog->len;
+ fp->size = fsize;
err = __sk_prepare_filter(fp);
if (err) {
@@ -853,6 +859,7 @@ void sk_decode_filter(struct sock_filter *filt, struct sock_filter *to)
int sk_get_filter(struct sock *sk, struct sock_filter __user *ubuf, unsigned int len)
{
struct sk_filter *filter;
+ unsigned int flen;
int i, ret;
lock_sock(sk);
@@ -861,15 +868,16 @@ int sk_get_filter(struct sock *sk, struct sock_filter __user *ubuf, unsigned int
ret = 0;
if (!filter)
goto out;
- ret = filter->len;
+
+ ret = flen = sk_bpf_flen(filter);
if (!len)
goto out;
ret = -EINVAL;
- if (len < filter->len)
+ if (len < flen)
goto out;
ret = -EFAULT;
- for (i = 0; i < filter->len; i++) {
+ for (i = 0; i < flen; i++) {
struct sock_filter fb;
sk_decode_filter(&filter->insns[i], &fb);
@@ -877,7 +885,7 @@ int sk_get_filter(struct sock *sk, struct sock_filter __user *ubuf, unsigned int
goto out;
}
- ret = filter->len;
+ ret = flen;
out:
release_sock(sk);
return ret;
diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c
index a0e9cf6..343bd58 100644
--- a/net/core/sock_diag.c
+++ b/net/core/sock_diag.c
@@ -65,7 +65,7 @@ int sock_diag_put_filterinfo(struct user_namespace *user_ns, struct sock *sk,
rcu_read_lock();
filter = rcu_dereference(sk->sk_filter);
- len = filter ? filter->len * sizeof(struct sock_filter) : 0;
+ len = filter ? filter->size : 0;
attr = nla_reserve(skb, attrtype, len);
if (attr == NULL) {
@@ -77,7 +77,7 @@ int sock_diag_put_filterinfo(struct user_namespace *user_ns, struct sock *sk,
struct sock_filter *fb = (struct sock_filter *)nla_data(attr);
int i;
- for (i = 0; i < filter->len; i++, fb++)
+ for (i = 0; i < sk_bpf_flen(filter); i++, fb++)
sk_decode_filter(&filter->insns[i], fb);
}
--
1.7.10.4
next prev parent reply other threads:[~2014-03-11 9:19 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-03-11 9:19 [PATCH RFC 0/9] socket filtering using nf_tables Pablo Neira Ayuso
2014-03-11 9:19 ` [PATCH RFC 1/9] net: rename fp->bpf_func to fp->run_filter Pablo Neira Ayuso
2014-03-11 9:19 ` Pablo Neira Ayuso [this message]
2014-03-11 9:19 ` [PATCH RFC 3/9] net: filter: generalise sk_filter_release Pablo Neira Ayuso
2014-03-11 9:19 ` [PATCH RFC 4/9] netfilter: nf_tables: move fast operations to header Pablo Neira Ayuso
2014-03-11 9:19 ` [PATCH RFC 5/9] netfilter: nf_tables: add nft_value_init Pablo Neira Ayuso
2014-03-11 9:19 ` [PATCH RFC 6/9] netfilter: nf_tables: rename nf_tables_core.c to nf_tables_nf.c Pablo Neira Ayuso
2014-03-11 9:19 ` [PATCH RFC 7/9] netfilter: nf_tables: move expression infrastructure to built-in core Pablo Neira Ayuso
2014-03-11 9:19 ` [PATCH RFC 8/9] netfilter: nf_tables: generalize verdict handling and introduce scopes Pablo Neira Ayuso
2014-03-11 9:19 ` [PATCH RFC 9/9] netfilter: nf_tables: add support for socket filtering Pablo Neira Ayuso
2014-03-11 10:29 ` [PATCH RFC 0/9] socket filtering using nf_tables Daniel Borkmann
2014-03-11 17:59 ` Alexei Starovoitov
2014-03-12 9:15 ` Pablo Neira Ayuso
2014-03-12 9:27 ` Pablo Neira Ayuso
2014-03-13 3:29 ` Alexei Starovoitov
2014-03-13 12:29 ` Pablo Neira Ayuso
2014-03-14 15:28 ` Alexei Starovoitov
2014-03-14 18:16 ` Pablo Neira Ayuso
2014-03-15 4:04 ` Alexei Starovoitov
2014-03-15 19:03 ` Pablo Neira Ayuso
2014-03-15 19:18 ` Alexei Starovoitov
2014-03-11 12:57 ` Andi Kleen
2014-04-04 15:24 ` David Miller
2014-04-04 15:27 ` Pablo Neira Ayuso
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1394529560-3490-3-git-send-email-pablo@netfilter.org \
--to=pablo@netfilter.org \
--cc=davem@davemloft.net \
--cc=kaber@trash.net \
--cc=netdev@vger.kernel.org \
--cc=netfilter-devel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).