]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
net: filter: add jited flag to indicate jit compiled filters
authorDaniel Borkmann <dborkman@redhat.com>
Fri, 28 Mar 2014 17:58:18 +0000 (18:58 +0100)
committerDavid S. Miller <davem@davemloft.net>
Mon, 31 Mar 2014 04:45:08 +0000 (00:45 -0400)
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: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
Cc: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
arch/arm/net/bpf_jit_32.c
arch/powerpc/net/bpf_jit_comp.c
arch/s390/net/bpf_jit_comp.c
arch/sparc/net/bpf_jit_comp.c
arch/x86/net/bpf_jit_comp.c
include/linux/filter.h
net/core/filter.c

index 7ddb9c83cdfc6c13c8d12848d6737a42f727f40b..6f879c319a9dbe9fc406946565da49a0e99f5eb8 100644 (file)
@@ -925,6 +925,7 @@ void bpf_jit_compile(struct sk_filter *fp)
                bpf_jit_dump(fp->len, alloc_size, 2, ctx.target);
 
        fp->bpf_func = (void *)ctx.target;
+       fp->jited = 1;
 out:
        kfree(ctx.offsets);
        return;
@@ -932,7 +933,7 @@ out:
 
 void bpf_jit_free(struct sk_filter *fp)
 {
-       if (fp->bpf_func != sk_run_filter)
+       if (fp->jited)
                module_free(NULL, fp->bpf_func);
        kfree(fp);
 }
index 4afad6c17d501be6e47e1399edc8cc9baea18ea1..808ce1cae21ab998439854e31eacaced66c044cb 100644 (file)
@@ -689,6 +689,7 @@ void bpf_jit_compile(struct sk_filter *fp)
                ((u64 *)image)[0] = (u64)code_base;
                ((u64 *)image)[1] = local_paca->kernel_toc;
                fp->bpf_func = (void *)image;
+               fp->jited = 1;
        }
 out:
        kfree(addrs);
@@ -697,7 +698,7 @@ out:
 
 void bpf_jit_free(struct sk_filter *fp)
 {
-       if (fp->bpf_func != sk_run_filter)
+       if (fp->jited)
                module_free(NULL, fp->bpf_func);
        kfree(fp);
 }
index 153f8f2cfd561cadca4c8bc1104424cbd12129d8..9c36dc398f9070afb4d6151d214623d1cbcf9f4a 100644 (file)
@@ -877,6 +877,7 @@ void bpf_jit_compile(struct sk_filter *fp)
        if (jit.start) {
                set_memory_ro((unsigned long)header, header->pages);
                fp->bpf_func = (void *) jit.start;
+               fp->jited = 1;
        }
 out:
        kfree(addrs);
@@ -887,10 +888,12 @@ void bpf_jit_free(struct sk_filter *fp)
        unsigned long addr = (unsigned long)fp->bpf_func & PAGE_MASK;
        struct bpf_binary_header *header = (void *)addr;
 
-       if (fp->bpf_func == sk_run_filter)
+       if (!fp->jited)
                goto free_filter;
+
        set_memory_rw(addr, header->pages);
        module_free(NULL, header);
+
 free_filter:
        kfree(fp);
 }
index d96d2a7c78eef85f3406f7450f065d93cc67024b..a82c6b2a9780cab8d882c2d13429f4889375229e 100644 (file)
@@ -809,6 +809,7 @@ cond_branch:                        f_offset = addrs[i + filter[i].jf];
        if (image) {
                bpf_flush_icache(image, image + proglen);
                fp->bpf_func = (void *)image;
+               fp->jited = 1;
        }
 out:
        kfree(addrs);
@@ -817,7 +818,7 @@ out:
 
 void bpf_jit_free(struct sk_filter *fp)
 {
-       if (fp->bpf_func != sk_run_filter)
+       if (fp->jited)
                module_free(NULL, fp->bpf_func);
        kfree(fp);
 }
index 293c57b74edcc3401067ee1f29e07bf3cdafad6e..dc017735bb91b7b2ec61f333b091c63accdb921b 100644 (file)
@@ -772,6 +772,7 @@ cond_branch:                        f_offset = addrs[i + filter[i].jf] - addrs[i];
                bpf_flush_icache(header, image + proglen);
                set_memory_ro((unsigned long)header, header->pages);
                fp->bpf_func = (void *)image;
+               fp->jited = 1;
        }
 out:
        kfree(addrs);
@@ -791,7 +792,7 @@ static void bpf_jit_free_deferred(struct work_struct *work)
 
 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);
                schedule_work(&fp->work);
        } else {
index e568c8ef896bf170de5578d7d898343a457b7724..e65e230873679285cdba21bee8f9c07429ef626d 100644 (file)
@@ -25,7 +25,8 @@ struct sock;
 struct sk_filter
 {
        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;
        unsigned int            (*bpf_func)(const struct sk_buff *skb,
                                            const struct sock_filter *filter);
index 65b75966e206acd95b280dff282aa882542c1250..bb3c76458ca9cc3c2f6aefc8022a224055c5fa65 100644 (file)
@@ -646,6 +646,7 @@ static int __sk_prepare_filter(struct sk_filter *fp)
        int err;
 
        fp->bpf_func = sk_run_filter;
+       fp->jited = 0;
 
        err = sk_chk_filter(fp->insns, fp->len);
        if (err)