Skip to content

Commit 60005c6

Browse files
committed
Merge branch 'bpf-next'
Daniel Borkmann says: ==================== BPF updates [ Set applies on top of current net-next but also on top of Alexei's latest patches. Please see individual patches for more details. ] Changelog: v1->v2: - Removed paragraph in 1st commit message - Rest stays the same ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents ca777ef + 286aad3 commit 60005c6

File tree

9 files changed

+108
-91
lines changed

9 files changed

+108
-91
lines changed

arch/arm/net/bpf_jit_32.c

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
#include <linux/compiler.h>
1313
#include <linux/errno.h>
1414
#include <linux/filter.h>
15-
#include <linux/moduleloader.h>
1615
#include <linux/netdevice.h>
1716
#include <linux/string.h>
1817
#include <linux/slab.h>
@@ -174,6 +173,15 @@ static inline bool is_load_to_a(u16 inst)
174173
}
175174
}
176175

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+
177185
static void build_prologue(struct jit_ctx *ctx)
178186
{
179187
u16 reg_set = saved_regs(ctx);
@@ -859,9 +867,11 @@ static int build_body(struct jit_ctx *ctx)
859867

860868
void bpf_jit_compile(struct bpf_prog *fp)
861869
{
870+
struct bpf_binary_header *header;
862871
struct jit_ctx ctx;
863872
unsigned tmp_idx;
864873
unsigned alloc_size;
874+
u8 *target_ptr;
865875

866876
if (!bpf_jit_enable)
867877
return;
@@ -897,13 +907,15 @@ void bpf_jit_compile(struct bpf_prog *fp)
897907
/* there's nothing after the epilogue on ARMv7 */
898908
build_epilogue(&ctx);
899909
#endif
900-
901910
alloc_size = 4 * ctx.idx;
902-
ctx.target = module_alloc(alloc_size);
903-
if (unlikely(ctx.target == NULL))
911+
header = bpf_jit_binary_alloc(alloc_size, &target_ptr,
912+
4, jit_fill_hole);
913+
if (header == NULL)
904914
goto out;
905915

916+
ctx.target = (u32 *) target_ptr;
906917
ctx.idx = 0;
918+
907919
build_prologue(&ctx);
908920
build_body(&ctx);
909921
build_epilogue(&ctx);
@@ -919,17 +931,25 @@ void bpf_jit_compile(struct bpf_prog *fp)
919931
/* there are 2 passes here */
920932
bpf_jit_dump(fp->len, alloc_size, 2, ctx.target);
921933

934+
set_memory_ro((unsigned long)header, header->pages);
922935
fp->bpf_func = (void *)ctx.target;
923-
fp->jited = 1;
936+
fp->jited = true;
924937
out:
925938
kfree(ctx.offsets);
926939
return;
927940
}
928941

929942
void bpf_jit_free(struct bpf_prog *fp)
930943
{
931-
if (fp->jited)
932-
module_free(NULL, fp->bpf_func);
944+
unsigned long addr = (unsigned long)fp->bpf_func & PAGE_MASK;
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);
933952

953+
free_filter:
934954
bpf_prog_unlock_free(fp);
935955
}

arch/mips/net/bpf_jit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1417,7 +1417,7 @@ void bpf_jit_compile(struct bpf_prog *fp)
14171417
bpf_jit_dump(fp->len, alloc_size, 2, ctx.target);
14181418

14191419
fp->bpf_func = (void *)ctx.target;
1420-
fp->jited = 1;
1420+
fp->jited = true;
14211421

14221422
out:
14231423
kfree(ctx.offsets);

arch/powerpc/net/bpf_jit_comp.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -686,7 +686,7 @@ void bpf_jit_compile(struct bpf_prog *fp)
686686
((u64 *)image)[0] = (u64)code_base;
687687
((u64 *)image)[1] = local_paca->kernel_toc;
688688
fp->bpf_func = (void *)image;
689-
fp->jited = 1;
689+
fp->jited = true;
690690
}
691691
out:
692692
kfree(addrs);

arch/s390/net/bpf_jit_comp.c

Lines changed: 10 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,9 @@
55
*
66
* Author(s): Martin Schwidefsky <[email protected]>
77
*/
8-
#include <linux/moduleloader.h>
98
#include <linux/netdevice.h>
109
#include <linux/if_vlan.h>
1110
#include <linux/filter.h>
12-
#include <linux/random.h>
1311
#include <linux/init.h>
1412
#include <asm/cacheflush.h>
1513
#include <asm/facility.h>
@@ -148,6 +146,12 @@ struct bpf_jit {
148146
ret; \
149147
})
150148

149+
static void bpf_jit_fill_hole(void *area, unsigned int size)
150+
{
151+
/* Fill whole space with illegal instructions */
152+
memset(area, 0, size);
153+
}
154+
151155
static void bpf_jit_prologue(struct bpf_jit *jit)
152156
{
153157
/* Save registers and create stack frame if necessary */
@@ -780,38 +784,6 @@ load_abs: if ((int) K < 0)
780784
return -1;
781785
}
782786

783-
/*
784-
* Note: for security reasons, bpf code will follow a randomly
785-
* sized amount of illegal instructions.
786-
*/
787-
struct bpf_binary_header {
788-
unsigned int pages;
789-
u8 image[];
790-
};
791-
792-
static struct bpf_binary_header *bpf_alloc_binary(unsigned int bpfsize,
793-
u8 **image_ptr)
794-
{
795-
struct bpf_binary_header *header;
796-
unsigned int sz, hole;
797-
798-
/* Most BPF filters are really small, but if some of them fill a page,
799-
* allow at least 128 extra bytes for illegal instructions.
800-
*/
801-
sz = round_up(bpfsize + sizeof(*header) + 128, PAGE_SIZE);
802-
header = module_alloc(sz);
803-
if (!header)
804-
return NULL;
805-
memset(header, 0, sz);
806-
header->pages = sz / PAGE_SIZE;
807-
hole = min(sz - (bpfsize + sizeof(*header)), PAGE_SIZE - sizeof(*header));
808-
/* Insert random number of illegal instructions before BPF code
809-
* and make sure the first instruction starts at an even address.
810-
*/
811-
*image_ptr = &header->image[(prandom_u32() % hole) & -2];
812-
return header;
813-
}
814-
815787
void bpf_jit_compile(struct bpf_prog *fp)
816788
{
817789
struct bpf_binary_header *header = NULL;
@@ -850,7 +822,8 @@ void bpf_jit_compile(struct bpf_prog *fp)
850822
size = prg_len + lit_len;
851823
if (size >= BPF_SIZE_MAX)
852824
goto out;
853-
header = bpf_alloc_binary(size, &jit.start);
825+
header = bpf_jit_binary_alloc(size, &jit.start,
826+
2, bpf_jit_fill_hole);
854827
if (!header)
855828
goto out;
856829
jit.prg = jit.mid = jit.start + prg_len;
@@ -869,7 +842,7 @@ void bpf_jit_compile(struct bpf_prog *fp)
869842
if (jit.start) {
870843
set_memory_ro((unsigned long)header, header->pages);
871844
fp->bpf_func = (void *) jit.start;
872-
fp->jited = 1;
845+
fp->jited = true;
873846
}
874847
out:
875848
kfree(addrs);
@@ -884,7 +857,7 @@ void bpf_jit_free(struct bpf_prog *fp)
884857
goto free_filter;
885858

886859
set_memory_rw(addr, header->pages);
887-
module_free(NULL, header);
860+
bpf_jit_binary_free(header);
888861

889862
free_filter:
890863
bpf_prog_unlock_free(fp);

arch/sparc/net/bpf_jit_comp.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -801,7 +801,7 @@ cond_branch: f_offset = addrs[i + filter[i].jf];
801801
if (image) {
802802
bpf_flush_icache(image, image + proglen);
803803
fp->bpf_func = (void *)image;
804-
fp->jited = 1;
804+
fp->jited = true;
805805
}
806806
out:
807807
kfree(addrs);

arch/x86/net/bpf_jit_comp.c

Lines changed: 12 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,10 @@
88
* as published by the Free Software Foundation; version 2
99
* of the License.
1010
*/
11-
#include <linux/moduleloader.h>
12-
#include <asm/cacheflush.h>
1311
#include <linux/netdevice.h>
1412
#include <linux/filter.h>
1513
#include <linux/if_vlan.h>
16-
#include <linux/random.h>
14+
#include <asm/cacheflush.h>
1715

1816
int bpf_jit_enable __read_mostly;
1917

@@ -109,39 +107,6 @@ static inline void bpf_flush_icache(void *start, void *end)
109107
#define CHOOSE_LOAD_FUNC(K, func) \
110108
((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative_offset : func) : func##_positive_offset)
111109

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-
145110
/* pick a register outside of BPF range for JIT internal work */
146111
#define AUX_REG (MAX_BPF_REG + 1)
147112

@@ -206,6 +171,12 @@ static inline u8 add_2reg(u8 byte, u32 dst_reg, u32 src_reg)
206171
return byte + reg2hex[dst_reg] + (reg2hex[src_reg] << 3);
207172
}
208173

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+
209180
struct jit_context {
210181
unsigned int cleanup_addr; /* epilogue code offset */
211182
bool seen_ld_abs;
@@ -959,7 +930,7 @@ void bpf_int_jit_compile(struct bpf_prog *prog)
959930
if (proglen <= 0) {
960931
image = NULL;
961932
if (header)
962-
module_free(NULL, header);
933+
bpf_jit_binary_free(header);
963934
goto out;
964935
}
965936
if (image) {
@@ -969,7 +940,8 @@ void bpf_int_jit_compile(struct bpf_prog *prog)
969940
break;
970941
}
971942
if (proglen == oldproglen) {
972-
header = bpf_alloc_binary(proglen, &image);
943+
header = bpf_jit_binary_alloc(proglen, &image,
944+
1, jit_fill_hole);
973945
if (!header)
974946
goto out;
975947
}
@@ -983,7 +955,7 @@ void bpf_int_jit_compile(struct bpf_prog *prog)
983955
bpf_flush_icache(header, image + proglen);
984956
set_memory_ro((unsigned long)header, header->pages);
985957
prog->bpf_func = (void *)image;
986-
prog->jited = 1;
958+
prog->jited = true;
987959
}
988960
out:
989961
kfree(addrs);
@@ -998,7 +970,7 @@ void bpf_jit_free(struct bpf_prog *fp)
998970
goto free_filter;
999971

1000972
set_memory_rw(addr, header->pages);
1001-
module_free(NULL, header);
973+
bpf_jit_binary_free(header);
1002974

1003975
free_filter:
1004976
bpf_prog_unlock_free(fp);

include/linux/filter.h

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -289,15 +289,20 @@ struct sock_fprog_kern {
289289
struct sock_filter *filter;
290290
};
291291

292+
struct bpf_binary_header {
293+
unsigned int pages;
294+
u8 image[];
295+
};
296+
292297
struct bpf_work_struct {
293298
struct bpf_prog *prog;
294299
struct work_struct work;
295300
};
296301

297302
struct bpf_prog {
298-
u32 pages; /* Number of allocated pages */
299-
u32 jited:1, /* Is our filter JIT'ed? */
300-
len:31; /* Number of filter blocks */
303+
u16 pages; /* Number of allocated pages */
304+
bool jited; /* Is our filter JIT'ed? */
305+
u32 len; /* Number of filter blocks */
301306
struct sock_fprog_kern *orig_prog; /* Original BPF program */
302307
struct bpf_work_struct *work; /* Deferred free work struct */
303308
unsigned int (*bpf_func)(const struct sk_buff *skb,
@@ -358,6 +363,14 @@ struct bpf_prog *bpf_prog_realloc(struct bpf_prog *fp_old, unsigned int size,
358363
gfp_t gfp_extra_flags);
359364
void __bpf_prog_free(struct bpf_prog *fp);
360365

366+
typedef void (*bpf_jit_fill_hole_t)(void *area, unsigned int size);
367+
368+
struct bpf_binary_header *
369+
bpf_jit_binary_alloc(unsigned int proglen, u8 **image_ptr,
370+
unsigned int alignment,
371+
bpf_jit_fill_hole_t bpf_fill_ill_insns);
372+
void bpf_jit_binary_free(struct bpf_binary_header *hdr);
373+
361374
static inline void bpf_prog_unlock_free(struct bpf_prog *fp)
362375
{
363376
bpf_prog_unlock_ro(fp);

0 commit comments

Comments
 (0)