diff options
-rw-r--r-- | arch/arm/net/bpf_jit_32.c | 3 | ||||
-rw-r--r-- | arch/powerpc/net/bpf_jit_comp.c | 3 | ||||
-rw-r--r-- | arch/s390/net/bpf_jit_comp.c | 5 | ||||
-rw-r--r-- | arch/sparc/net/bpf_jit_comp.c | 3 | ||||
-rw-r--r-- | arch/x86/net/bpf_jit_comp.c | 3 | ||||
-rw-r--r-- | include/linux/filter.h | 3 | ||||
-rw-r--r-- | net/core/filter.c | 1 |
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; | ||
928 | out: | 929 | out: |
929 | kfree(ctx.offsets); | 930 | kfree(ctx.offsets); |
930 | return; | 931 | return; |
@@ -932,7 +933,7 @@ out: | |||
932 | 933 | ||
933 | void bpf_jit_free(struct sk_filter *fp) | 934 | void 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 | } |
693 | out: | 694 | out: |
694 | kfree(addrs); | 695 | kfree(addrs); |
@@ -697,7 +698,7 @@ out: | |||
697 | 698 | ||
698 | void bpf_jit_free(struct sk_filter *fp) | 699 | void 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 | } |
881 | out: | 882 | out: |
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 | |||
894 | free_filter: | 897 | free_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 | } |
813 | out: | 814 | out: |
814 | kfree(addrs); | 815 | kfree(addrs); |
@@ -817,7 +818,7 @@ out: | |||
817 | 818 | ||
818 | void bpf_jit_free(struct sk_filter *fp) | 819 | void 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 | } |
776 | out: | 777 | out: |
777 | kfree(addrs); | 778 | kfree(addrs); |
@@ -791,7 +792,7 @@ static void bpf_jit_free_deferred(struct work_struct *work) | |||
791 | 792 | ||
792 | void bpf_jit_free(struct sk_filter *fp) | 793 | void 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; | |||
25 | struct sk_filter | 25 | struct 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) |