aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/net/bpf_jit_comp.c50
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
18int bpf_jit_enable __read_mostly; 16int 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
112struct 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
120static 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
174static void jit_fill_hole(void *area, unsigned int size)
175{
176 /* fill whole space with int3 instructions */
177 memset(area, 0xcc, size);
178}
179
209struct jit_context { 180struct 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
1003free_filter: 975free_filter:
1004 bpf_prog_unlock_free(fp); 976 bpf_prog_unlock_free(fp);