diff options
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/net/bpf_jit_32.c | 32 |
1 files changed, 26 insertions, 6 deletions
diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c index a76623bcf722..2d1a5b93d91c 100644 --- a/arch/arm/net/bpf_jit_32.c +++ b/arch/arm/net/bpf_jit_32.c | |||
@@ -12,7 +12,6 @@ | |||
12 | #include <linux/compiler.h> | 12 | #include <linux/compiler.h> |
13 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
14 | #include <linux/filter.h> | 14 | #include <linux/filter.h> |
15 | #include <linux/moduleloader.h> | ||
16 | #include <linux/netdevice.h> | 15 | #include <linux/netdevice.h> |
17 | #include <linux/string.h> | 16 | #include <linux/string.h> |
18 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
@@ -174,6 +173,15 @@ static inline bool is_load_to_a(u16 inst) | |||
174 | } | 173 | } |
175 | } | 174 | } |
176 | 175 | ||
176 | static void jit_fill_hole(void *area, unsigned int size) | ||
177 | { | ||
178 | /* Insert illegal UND instructions. */ | ||
179 | u32 *ptr, fill_ins = 0xe7ffffff; | ||
180 | /* We are guaranteed to have aligned memory. */ | ||
181 | for (ptr = area; size >= sizeof(u32); size -= sizeof(u32)) | ||
182 | *ptr++ = fill_ins; | ||
183 | } | ||
184 | |||
177 | static void build_prologue(struct jit_ctx *ctx) | 185 | static void build_prologue(struct jit_ctx *ctx) |
178 | { | 186 | { |
179 | u16 reg_set = saved_regs(ctx); | 187 | u16 reg_set = saved_regs(ctx); |
@@ -859,9 +867,11 @@ b_epilogue: | |||
859 | 867 | ||
860 | void bpf_jit_compile(struct bpf_prog *fp) | 868 | void bpf_jit_compile(struct bpf_prog *fp) |
861 | { | 869 | { |
870 | struct bpf_binary_header *header; | ||
862 | struct jit_ctx ctx; | 871 | struct jit_ctx ctx; |
863 | unsigned tmp_idx; | 872 | unsigned tmp_idx; |
864 | unsigned alloc_size; | 873 | unsigned alloc_size; |
874 | u8 *target_ptr; | ||
865 | 875 | ||
866 | if (!bpf_jit_enable) | 876 | if (!bpf_jit_enable) |
867 | return; | 877 | return; |
@@ -897,13 +907,15 @@ void bpf_jit_compile(struct bpf_prog *fp) | |||
897 | /* there's nothing after the epilogue on ARMv7 */ | 907 | /* there's nothing after the epilogue on ARMv7 */ |
898 | build_epilogue(&ctx); | 908 | build_epilogue(&ctx); |
899 | #endif | 909 | #endif |
900 | |||
901 | alloc_size = 4 * ctx.idx; | 910 | alloc_size = 4 * ctx.idx; |
902 | ctx.target = module_alloc(alloc_size); | 911 | header = bpf_jit_binary_alloc(alloc_size, &target_ptr, |
903 | if (unlikely(ctx.target == NULL)) | 912 | 4, jit_fill_hole); |
913 | if (header == NULL) | ||
904 | goto out; | 914 | goto out; |
905 | 915 | ||
916 | ctx.target = (u32 *) target_ptr; | ||
906 | ctx.idx = 0; | 917 | ctx.idx = 0; |
918 | |||
907 | build_prologue(&ctx); | 919 | build_prologue(&ctx); |
908 | build_body(&ctx); | 920 | build_body(&ctx); |
909 | build_epilogue(&ctx); | 921 | build_epilogue(&ctx); |
@@ -919,6 +931,7 @@ void bpf_jit_compile(struct bpf_prog *fp) | |||
919 | /* there are 2 passes here */ | 931 | /* there are 2 passes here */ |
920 | bpf_jit_dump(fp->len, alloc_size, 2, ctx.target); | 932 | bpf_jit_dump(fp->len, alloc_size, 2, ctx.target); |
921 | 933 | ||
934 | set_memory_ro((unsigned long)header, header->pages); | ||
922 | fp->bpf_func = (void *)ctx.target; | 935 | fp->bpf_func = (void *)ctx.target; |
923 | fp->jited = 1; | 936 | fp->jited = 1; |
924 | out: | 937 | out: |
@@ -928,8 +941,15 @@ out: | |||
928 | 941 | ||
929 | void bpf_jit_free(struct bpf_prog *fp) | 942 | void bpf_jit_free(struct bpf_prog *fp) |
930 | { | 943 | { |
931 | if (fp->jited) | 944 | unsigned long addr = (unsigned long)fp->bpf_func & PAGE_MASK; |
932 | module_free(NULL, fp->bpf_func); | 945 | struct bpf_binary_header *header = (void *)addr; |
946 | |||
947 | if (!fp->jited) | ||
948 | goto free_filter; | ||
949 | |||
950 | set_memory_rw(addr, header->pages); | ||
951 | bpf_jit_binary_free(header); | ||
933 | 952 | ||
953 | free_filter: | ||
934 | bpf_prog_unlock_free(fp); | 954 | bpf_prog_unlock_free(fp); |
935 | } | 955 | } |