提交 f8bbbfc3 编写于 作者: D Daniel Borkmann 提交者: David S. Miller

net: filter: add jited flag to indicate jit compiled filters

This patch adds a jited flag into sk_filter struct in order to indicate
whether a filter is currently jited or not. The size of sk_filter is
not being expanded as the 32 bit 'len' member allows upper bits to be
reused since a filter can currently only grow as large as BPF_MAXINSNS.

Therefore, there's enough room also for other in future needed flags to
reuse 'len' field if necessary. The jited flag also allows for having
alternative interpreter functions running as currently, we can only
detect jit compiled filters by testing fp->bpf_func to not equal the
address of sk_run_filter().

Joint work with Alexei Starovoitov.
Signed-off-by: NAlexei Starovoitov <ast@plumgrid.com>
Signed-off-by: NDaniel Borkmann <dborkman@redhat.com>
Cc: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 64c27237
...@@ -925,6 +925,7 @@ void bpf_jit_compile(struct sk_filter *fp) ...@@ -925,6 +925,7 @@ void bpf_jit_compile(struct sk_filter *fp)
bpf_jit_dump(fp->len, alloc_size, 2, ctx.target); bpf_jit_dump(fp->len, alloc_size, 2, ctx.target);
fp->bpf_func = (void *)ctx.target; fp->bpf_func = (void *)ctx.target;
fp->jited = 1;
out: out:
kfree(ctx.offsets); kfree(ctx.offsets);
return; return;
...@@ -932,7 +933,7 @@ void bpf_jit_compile(struct sk_filter *fp) ...@@ -932,7 +933,7 @@ void bpf_jit_compile(struct sk_filter *fp)
void bpf_jit_free(struct sk_filter *fp) void bpf_jit_free(struct sk_filter *fp)
{ {
if (fp->bpf_func != sk_run_filter) if (fp->jited)
module_free(NULL, fp->bpf_func); module_free(NULL, fp->bpf_func);
kfree(fp); kfree(fp);
} }
...@@ -689,6 +689,7 @@ void bpf_jit_compile(struct sk_filter *fp) ...@@ -689,6 +689,7 @@ void bpf_jit_compile(struct sk_filter *fp)
((u64 *)image)[0] = (u64)code_base; ((u64 *)image)[0] = (u64)code_base;
((u64 *)image)[1] = local_paca->kernel_toc; ((u64 *)image)[1] = local_paca->kernel_toc;
fp->bpf_func = (void *)image; fp->bpf_func = (void *)image;
fp->jited = 1;
} }
out: out:
kfree(addrs); kfree(addrs);
...@@ -697,7 +698,7 @@ void bpf_jit_compile(struct sk_filter *fp) ...@@ -697,7 +698,7 @@ void bpf_jit_compile(struct sk_filter *fp)
void bpf_jit_free(struct sk_filter *fp) void bpf_jit_free(struct sk_filter *fp)
{ {
if (fp->bpf_func != sk_run_filter) if (fp->jited)
module_free(NULL, fp->bpf_func); module_free(NULL, fp->bpf_func);
kfree(fp); kfree(fp);
} }
...@@ -877,6 +877,7 @@ void bpf_jit_compile(struct sk_filter *fp) ...@@ -877,6 +877,7 @@ void bpf_jit_compile(struct sk_filter *fp)
if (jit.start) { if (jit.start) {
set_memory_ro((unsigned long)header, header->pages); set_memory_ro((unsigned long)header, header->pages);
fp->bpf_func = (void *) jit.start; fp->bpf_func = (void *) jit.start;
fp->jited = 1;
} }
out: out:
kfree(addrs); kfree(addrs);
...@@ -887,10 +888,12 @@ void bpf_jit_free(struct sk_filter *fp) ...@@ -887,10 +888,12 @@ void bpf_jit_free(struct sk_filter *fp)
unsigned long addr = (unsigned long)fp->bpf_func & PAGE_MASK; unsigned long addr = (unsigned long)fp->bpf_func & PAGE_MASK;
struct bpf_binary_header *header = (void *)addr; struct bpf_binary_header *header = (void *)addr;
if (fp->bpf_func == sk_run_filter) if (!fp->jited)
goto free_filter; goto free_filter;
set_memory_rw(addr, header->pages); set_memory_rw(addr, header->pages);
module_free(NULL, header); module_free(NULL, header);
free_filter: free_filter:
kfree(fp); kfree(fp);
} }
...@@ -809,6 +809,7 @@ cond_branch: f_offset = addrs[i + filter[i].jf]; ...@@ -809,6 +809,7 @@ cond_branch: f_offset = addrs[i + filter[i].jf];
if (image) { if (image) {
bpf_flush_icache(image, image + proglen); bpf_flush_icache(image, image + proglen);
fp->bpf_func = (void *)image; fp->bpf_func = (void *)image;
fp->jited = 1;
} }
out: out:
kfree(addrs); kfree(addrs);
...@@ -817,7 +818,7 @@ cond_branch: f_offset = addrs[i + filter[i].jf]; ...@@ -817,7 +818,7 @@ cond_branch: f_offset = addrs[i + filter[i].jf];
void bpf_jit_free(struct sk_filter *fp) void bpf_jit_free(struct sk_filter *fp)
{ {
if (fp->bpf_func != sk_run_filter) if (fp->jited)
module_free(NULL, fp->bpf_func); module_free(NULL, fp->bpf_func);
kfree(fp); kfree(fp);
} }
...@@ -772,6 +772,7 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; ...@@ -772,6 +772,7 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i];
bpf_flush_icache(header, image + proglen); bpf_flush_icache(header, image + proglen);
set_memory_ro((unsigned long)header, header->pages); set_memory_ro((unsigned long)header, header->pages);
fp->bpf_func = (void *)image; fp->bpf_func = (void *)image;
fp->jited = 1;
} }
out: out:
kfree(addrs); kfree(addrs);
...@@ -791,7 +792,7 @@ static void bpf_jit_free_deferred(struct work_struct *work) ...@@ -791,7 +792,7 @@ static void bpf_jit_free_deferred(struct work_struct *work)
void bpf_jit_free(struct sk_filter *fp) void bpf_jit_free(struct sk_filter *fp)
{ {
if (fp->bpf_func != sk_run_filter) { if (fp->jited) {
INIT_WORK(&fp->work, bpf_jit_free_deferred); INIT_WORK(&fp->work, bpf_jit_free_deferred);
schedule_work(&fp->work); schedule_work(&fp->work);
} else { } else {
......
...@@ -25,7 +25,8 @@ struct sock; ...@@ -25,7 +25,8 @@ struct sock;
struct sk_filter struct sk_filter
{ {
atomic_t refcnt; atomic_t refcnt;
unsigned int len; /* Number of filter blocks */ u32 jited:1, /* Is our filter JIT'ed? */
len:31; /* Number of filter blocks */
struct rcu_head rcu; struct rcu_head rcu;
unsigned int (*bpf_func)(const struct sk_buff *skb, unsigned int (*bpf_func)(const struct sk_buff *skb,
const struct sock_filter *filter); const struct sock_filter *filter);
......
...@@ -646,6 +646,7 @@ static int __sk_prepare_filter(struct sk_filter *fp) ...@@ -646,6 +646,7 @@ static int __sk_prepare_filter(struct sk_filter *fp)
int err; int err;
fp->bpf_func = sk_run_filter; fp->bpf_func = sk_run_filter;
fp->jited = 0;
err = sk_chk_filter(fp->insns, fp->len); err = sk_chk_filter(fp->insns, fp->len);
if (err) if (err)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册