diff options
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/net/bpf_jit_comp.c | 50 |
1 files changed, 11 insertions, 39 deletions
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index 06f8c17f5484..9de0b5476b0c 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c | |||
@@ -8,12 +8,10 @@ | |||
8 | * as published by the Free Software Foundation; version 2 | 8 | * as published by the Free Software Foundation; version 2 |
9 | * of the License. | 9 | * of the License. |
10 | */ | 10 | */ |
11 | #include <linux/moduleloader.h> | ||
12 | #include <asm/cacheflush.h> | ||
13 | #include <linux/netdevice.h> | 11 | #include <linux/netdevice.h> |
14 | #include <linux/filter.h> | 12 | #include <linux/filter.h> |
15 | #include <linux/if_vlan.h> | 13 | #include <linux/if_vlan.h> |
16 | #include <linux/random.h> | 14 | #include <asm/cacheflush.h> |
17 | 15 | ||
18 | int bpf_jit_enable __read_mostly; | 16 | int bpf_jit_enable __read_mostly; |
19 | 17 | ||
@@ -109,39 +107,6 @@ static inline void bpf_flush_icache(void *start, void *end) | |||
109 | #define CHOOSE_LOAD_FUNC(K, func) \ | 107 | #define CHOOSE_LOAD_FUNC(K, func) \ |
110 | ((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative_offset : func) : func##_positive_offset) | 108 | ((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative_offset : func) : func##_positive_offset) |
111 | 109 | ||
112 | struct bpf_binary_header { | ||
113 | unsigned int pages; | ||
114 | /* Note : for security reasons, bpf code will follow a randomly | ||
115 | * sized amount of int3 instructions | ||
116 | */ | ||
117 | u8 image[]; | ||
118 | }; | ||
119 | |||
120 | static struct bpf_binary_header *bpf_alloc_binary(unsigned int proglen, | ||
121 | u8 **image_ptr) | ||
122 | { | ||
123 | unsigned int sz, hole; | ||
124 | struct bpf_binary_header *header; | ||
125 | |||
126 | /* Most of BPF filters are really small, | ||
127 | * but if some of them fill a page, allow at least | ||
128 | * 128 extra bytes to insert a random section of int3 | ||
129 | */ | ||
130 | sz = round_up(proglen + sizeof(*header) + 128, PAGE_SIZE); | ||
131 | header = module_alloc(sz); | ||
132 | if (!header) | ||
133 | return NULL; | ||
134 | |||
135 | memset(header, 0xcc, sz); /* fill whole space with int3 instructions */ | ||
136 | |||
137 | header->pages = sz / PAGE_SIZE; | ||
138 | hole = min(sz - (proglen + sizeof(*header)), PAGE_SIZE - sizeof(*header)); | ||
139 | |||
140 | /* insert a random number of int3 instructions before BPF code */ | ||
141 | *image_ptr = &header->image[prandom_u32() % hole]; | ||
142 | return header; | ||
143 | } | ||
144 | |||
145 | /* pick a register outside of BPF range for JIT internal work */ | 110 | /* pick a register outside of BPF range for JIT internal work */ |
146 | #define AUX_REG (MAX_BPF_REG + 1) | 111 | #define AUX_REG (MAX_BPF_REG + 1) |
147 | 112 | ||
@@ -206,6 +171,12 @@ static inline u8 add_2reg(u8 byte, u32 dst_reg, u32 src_reg) | |||
206 | return byte + reg2hex[dst_reg] + (reg2hex[src_reg] << 3); | 171 | return byte + reg2hex[dst_reg] + (reg2hex[src_reg] << 3); |
207 | } | 172 | } |
208 | 173 | ||
174 | static void jit_fill_hole(void *area, unsigned int size) | ||
175 | { | ||
176 | /* fill whole space with int3 instructions */ | ||
177 | memset(area, 0xcc, size); | ||
178 | } | ||
179 | |||
209 | struct jit_context { | 180 | struct jit_context { |
210 | unsigned int cleanup_addr; /* epilogue code offset */ | 181 | unsigned int cleanup_addr; /* epilogue code offset */ |
211 | bool seen_ld_abs; | 182 | bool seen_ld_abs; |
@@ -959,7 +930,7 @@ void bpf_int_jit_compile(struct bpf_prog *prog) | |||
959 | if (proglen <= 0) { | 930 | if (proglen <= 0) { |
960 | image = NULL; | 931 | image = NULL; |
961 | if (header) | 932 | if (header) |
962 | module_free(NULL, header); | 933 | bpf_jit_binary_free(header); |
963 | goto out; | 934 | goto out; |
964 | } | 935 | } |
965 | if (image) { | 936 | if (image) { |
@@ -969,7 +940,8 @@ void bpf_int_jit_compile(struct bpf_prog *prog) | |||
969 | break; | 940 | break; |
970 | } | 941 | } |
971 | if (proglen == oldproglen) { | 942 | if (proglen == oldproglen) { |
972 | header = bpf_alloc_binary(proglen, &image); | 943 | header = bpf_jit_binary_alloc(proglen, &image, |
944 | 1, jit_fill_hole); | ||
973 | if (!header) | 945 | if (!header) |
974 | goto out; | 946 | goto out; |
975 | } | 947 | } |
@@ -998,7 +970,7 @@ void bpf_jit_free(struct bpf_prog *fp) | |||
998 | goto free_filter; | 970 | goto free_filter; |
999 | 971 | ||
1000 | set_memory_rw(addr, header->pages); | 972 | set_memory_rw(addr, header->pages); |
1001 | module_free(NULL, header); | 973 | bpf_jit_binary_free(header); |
1002 | 974 | ||
1003 | free_filter: | 975 | free_filter: |
1004 | bpf_prog_unlock_free(fp); | 976 | bpf_prog_unlock_free(fp); |