aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Borkmann <dborkman@redhat.com>2014-03-28 13:58:18 -0400
committerDavid S. Miller <davem@davemloft.net>2014-03-31 00:45:08 -0400
commitf8bbbfc3b97f4c7a6c7c23185e520b22bfc3a21d (patch)
treee5d935854be9ec9d0c3024fbe3316cfce9e68349
parent64c27237a07129758e33f5f824ba5c33b7f57417 (diff)
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: 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>
-rw-r--r--arch/arm/net/bpf_jit_32.c3
-rw-r--r--arch/powerpc/net/bpf_jit_comp.c3
-rw-r--r--arch/s390/net/bpf_jit_comp.c5
-rw-r--r--arch/sparc/net/bpf_jit_comp.c3
-rw-r--r--arch/x86/net/bpf_jit_comp.c3
-rw-r--r--include/linux/filter.h3
-rw-r--r--net/core/filter.c1
7 files changed, 15 insertions, 6 deletions
diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
index 7ddb9c83cdfc..6f879c319a9d 100644
--- a/arch/arm/net/bpf_jit_32.c
+++ b/arch/arm/net/bpf_jit_32.c
@@ -925,6 +925,7 @@ void bpf_jit_compile(struct sk_filter *fp)
925 bpf_jit_dump(fp->len, alloc_size, 2, ctx.target); 925 bpf_jit_dump(fp->len, alloc_size, 2, ctx.target);
926 926
927 fp->bpf_func = (void *)ctx.target; 927 fp->bpf_func = (void *)ctx.target;
928 fp->jited = 1;
928out: 929out:
929 kfree(ctx.offsets); 930 kfree(ctx.offsets);
930 return; 931 return;
@@ -932,7 +933,7 @@ out:
932 933
933void bpf_jit_free(struct sk_filter *fp) 934void bpf_jit_free(struct sk_filter *fp)
934{ 935{
935 if (fp->bpf_func != sk_run_filter) 936 if (fp->jited)
936 module_free(NULL, fp->bpf_func); 937 module_free(NULL, fp->bpf_func);
937 kfree(fp); 938 kfree(fp);
938} 939}
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index 4afad6c17d50..808ce1cae21a 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -689,6 +689,7 @@ void bpf_jit_compile(struct sk_filter *fp)
689 ((u64 *)image)[0] = (u64)code_base; 689 ((u64 *)image)[0] = (u64)code_base;
690 ((u64 *)image)[1] = local_paca->kernel_toc; 690 ((u64 *)image)[1] = local_paca->kernel_toc;
691 fp->bpf_func = (void *)image; 691 fp->bpf_func = (void *)image;
692 fp->jited = 1;
692 } 693 }
693out: 694out:
694 kfree(addrs); 695 kfree(addrs);
@@ -697,7 +698,7 @@ out:
697 698
698void bpf_jit_free(struct sk_filter *fp) 699void bpf_jit_free(struct sk_filter *fp)
699{ 700{
700 if (fp->bpf_func != sk_run_filter) 701 if (fp->jited)
701 module_free(NULL, fp->bpf_func); 702 module_free(NULL, fp->bpf_func);
702 kfree(fp); 703 kfree(fp);
703} 704}
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
index 153f8f2cfd56..9c36dc398f90 100644
--- a/arch/s390/net/bpf_jit_comp.c
+++ b/arch/s390/net/bpf_jit_comp.c
@@ -877,6 +877,7 @@ void bpf_jit_compile(struct sk_filter *fp)
877 if (jit.start) { 877 if (jit.start) {
878 set_memory_ro((unsigned long)header, header->pages); 878 set_memory_ro((unsigned long)header, header->pages);
879 fp->bpf_func = (void *) jit.start; 879 fp->bpf_func = (void *) jit.start;
880 fp->jited = 1;
880 } 881 }
881out: 882out:
882 kfree(addrs); 883 kfree(addrs);
@@ -887,10 +888,12 @@ void bpf_jit_free(struct sk_filter *fp)
887 unsigned long addr = (unsigned long)fp->bpf_func & PAGE_MASK; 888 unsigned long addr = (unsigned long)fp->bpf_func & PAGE_MASK;
888 struct bpf_binary_header *header = (void *)addr; 889 struct bpf_binary_header *header = (void *)addr;
889 890
890 if (fp->bpf_func == sk_run_filter) 891 if (!fp->jited)
891 goto free_filter; 892 goto free_filter;
893
892 set_memory_rw(addr, header->pages); 894 set_memory_rw(addr, header->pages);
893 module_free(NULL, header); 895 module_free(NULL, header);
896
894free_filter: 897free_filter:
895 kfree(fp); 898 kfree(fp);
896} 899}
diff --git a/arch/sparc/net/bpf_jit_comp.c b/arch/sparc/net/bpf_jit_comp.c
index d96d2a7c78ee..a82c6b2a9780 100644
--- a/arch/sparc/net/bpf_jit_comp.c
+++ b/arch/sparc/net/bpf_jit_comp.c
@@ -809,6 +809,7 @@ cond_branch: f_offset = addrs[i + filter[i].jf];
809 if (image) { 809 if (image) {
810 bpf_flush_icache(image, image + proglen); 810 bpf_flush_icache(image, image + proglen);
811 fp->bpf_func = (void *)image; 811 fp->bpf_func = (void *)image;
812 fp->jited = 1;
812 } 813 }
813out: 814out:
814 kfree(addrs); 815 kfree(addrs);
@@ -817,7 +818,7 @@ out:
817 818
818void bpf_jit_free(struct sk_filter *fp) 819void bpf_jit_free(struct sk_filter *fp)
819{ 820{
820 if (fp->bpf_func != sk_run_filter) 821 if (fp->jited)
821 module_free(NULL, fp->bpf_func); 822 module_free(NULL, fp->bpf_func);
822 kfree(fp); 823 kfree(fp);
823} 824}
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index 293c57b74edc..dc017735bb91 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -772,6 +772,7 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i];
772 bpf_flush_icache(header, image + proglen); 772 bpf_flush_icache(header, image + proglen);
773 set_memory_ro((unsigned long)header, header->pages); 773 set_memory_ro((unsigned long)header, header->pages);
774 fp->bpf_func = (void *)image; 774 fp->bpf_func = (void *)image;
775 fp->jited = 1;
775 } 776 }
776out: 777out:
777 kfree(addrs); 778 kfree(addrs);
@@ -791,7 +792,7 @@ static void bpf_jit_free_deferred(struct work_struct *work)
791 792
792void bpf_jit_free(struct sk_filter *fp) 793void bpf_jit_free(struct sk_filter *fp)
793{ 794{
794 if (fp->bpf_func != sk_run_filter) { 795 if (fp->jited) {
795 INIT_WORK(&fp->work, bpf_jit_free_deferred); 796 INIT_WORK(&fp->work, bpf_jit_free_deferred);
796 schedule_work(&fp->work); 797 schedule_work(&fp->work);
797 } else { 798 } else {
diff --git a/include/linux/filter.h b/include/linux/filter.h
index e568c8ef896b..e65e23087367 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -25,7 +25,8 @@ struct sock;
25struct sk_filter 25struct sk_filter
26{ 26{
27 atomic_t refcnt; 27 atomic_t refcnt;
28 unsigned int len; /* Number of filter blocks */ 28 u32 jited:1, /* Is our filter JIT'ed? */
29 len:31; /* Number of filter blocks */
29 struct rcu_head rcu; 30 struct rcu_head rcu;
30 unsigned int (*bpf_func)(const struct sk_buff *skb, 31 unsigned int (*bpf_func)(const struct sk_buff *skb,
31 const struct sock_filter *filter); 32 const struct sock_filter *filter);
diff --git a/net/core/filter.c b/net/core/filter.c
index 65b75966e206..bb3c76458ca9 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -646,6 +646,7 @@ static int __sk_prepare_filter(struct sk_filter *fp)
646 int err; 646 int err;
647 647
648 fp->bpf_func = sk_run_filter; 648 fp->bpf_func = sk_run_filter;
649 fp->jited = 0;
649 650
650 err = sk_chk_filter(fp->insns, fp->len); 651 err = sk_chk_filter(fp->insns, fp->len);
651 if (err) 652 if (err)