diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm64/net/bpf_jit_comp.c | 39 |
1 files changed, 30 insertions, 9 deletions
diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c index 7ae33545535b..71088952ed27 100644 --- a/arch/arm64/net/bpf_jit_comp.c +++ b/arch/arm64/net/bpf_jit_comp.c | |||
@@ -19,12 +19,13 @@ | |||
19 | #define pr_fmt(fmt) "bpf_jit: " fmt | 19 | #define pr_fmt(fmt) "bpf_jit: " fmt |
20 | 20 | ||
21 | #include <linux/filter.h> | 21 | #include <linux/filter.h> |
22 | #include <linux/moduleloader.h> | ||
23 | #include <linux/printk.h> | 22 | #include <linux/printk.h> |
24 | #include <linux/skbuff.h> | 23 | #include <linux/skbuff.h> |
25 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | |||
26 | #include <asm/byteorder.h> | 26 | #include <asm/byteorder.h> |
27 | #include <asm/cacheflush.h> | 27 | #include <asm/cacheflush.h> |
28 | #include <asm/debug-monitors.h> | ||
28 | 29 | ||
29 | #include "bpf_jit.h" | 30 | #include "bpf_jit.h" |
30 | 31 | ||
@@ -119,6 +120,14 @@ static inline int bpf2a64_offset(int bpf_to, int bpf_from, | |||
119 | return to - from; | 120 | return to - from; |
120 | } | 121 | } |
121 | 122 | ||
123 | static void jit_fill_hole(void *area, unsigned int size) | ||
124 | { | ||
125 | u32 *ptr; | ||
126 | /* We are guaranteed to have aligned memory. */ | ||
127 | for (ptr = area; size >= sizeof(u32); size -= sizeof(u32)) | ||
128 | *ptr++ = cpu_to_le32(AARCH64_BREAK_FAULT); | ||
129 | } | ||
130 | |||
122 | static inline int epilogue_offset(const struct jit_ctx *ctx) | 131 | static inline int epilogue_offset(const struct jit_ctx *ctx) |
123 | { | 132 | { |
124 | int to = ctx->offset[ctx->prog->len - 1]; | 133 | int to = ctx->offset[ctx->prog->len - 1]; |
@@ -613,8 +622,10 @@ void bpf_jit_compile(struct bpf_prog *prog) | |||
613 | 622 | ||
614 | void bpf_int_jit_compile(struct bpf_prog *prog) | 623 | void bpf_int_jit_compile(struct bpf_prog *prog) |
615 | { | 624 | { |
625 | struct bpf_binary_header *header; | ||
616 | struct jit_ctx ctx; | 626 | struct jit_ctx ctx; |
617 | int image_size; | 627 | int image_size; |
628 | u8 *image_ptr; | ||
618 | 629 | ||
619 | if (!bpf_jit_enable) | 630 | if (!bpf_jit_enable) |
620 | return; | 631 | return; |
@@ -636,23 +647,25 @@ void bpf_int_jit_compile(struct bpf_prog *prog) | |||
636 | goto out; | 647 | goto out; |
637 | 648 | ||
638 | build_prologue(&ctx); | 649 | build_prologue(&ctx); |
639 | |||
640 | build_epilogue(&ctx); | 650 | build_epilogue(&ctx); |
641 | 651 | ||
642 | /* Now we know the actual image size. */ | 652 | /* Now we know the actual image size. */ |
643 | image_size = sizeof(u32) * ctx.idx; | 653 | image_size = sizeof(u32) * ctx.idx; |
644 | ctx.image = module_alloc(image_size); | 654 | header = bpf_jit_binary_alloc(image_size, &image_ptr, |
645 | if (unlikely(ctx.image == NULL)) | 655 | sizeof(u32), jit_fill_hole); |
656 | if (header == NULL) | ||
646 | goto out; | 657 | goto out; |
647 | 658 | ||
648 | /* 2. Now, the actual pass. */ | 659 | /* 2. Now, the actual pass. */ |
649 | 660 | ||
661 | ctx.image = (u32 *)image_ptr; | ||
650 | ctx.idx = 0; | 662 | ctx.idx = 0; |
663 | |||
651 | build_prologue(&ctx); | 664 | build_prologue(&ctx); |
652 | 665 | ||
653 | ctx.body_offset = ctx.idx; | 666 | ctx.body_offset = ctx.idx; |
654 | if (build_body(&ctx)) { | 667 | if (build_body(&ctx)) { |
655 | module_free(NULL, ctx.image); | 668 | bpf_jit_binary_free(header); |
656 | goto out; | 669 | goto out; |
657 | } | 670 | } |
658 | 671 | ||
@@ -663,17 +676,25 @@ void bpf_int_jit_compile(struct bpf_prog *prog) | |||
663 | bpf_jit_dump(prog->len, image_size, 2, ctx.image); | 676 | bpf_jit_dump(prog->len, image_size, 2, ctx.image); |
664 | 677 | ||
665 | bpf_flush_icache(ctx.image, ctx.image + ctx.idx); | 678 | bpf_flush_icache(ctx.image, ctx.image + ctx.idx); |
679 | |||
680 | set_memory_ro((unsigned long)header, header->pages); | ||
666 | prog->bpf_func = (void *)ctx.image; | 681 | prog->bpf_func = (void *)ctx.image; |
667 | prog->jited = 1; | 682 | prog->jited = 1; |
668 | |||
669 | out: | 683 | out: |
670 | kfree(ctx.offset); | 684 | kfree(ctx.offset); |
671 | } | 685 | } |
672 | 686 | ||
673 | void bpf_jit_free(struct bpf_prog *prog) | 687 | void bpf_jit_free(struct bpf_prog *prog) |
674 | { | 688 | { |
675 | if (prog->jited) | 689 | unsigned long addr = (unsigned long)prog->bpf_func & PAGE_MASK; |
676 | module_free(NULL, prog->bpf_func); | 690 | struct bpf_binary_header *header = (void *)addr; |
691 | |||
692 | if (!prog->jited) | ||
693 | goto free_filter; | ||
694 | |||
695 | set_memory_rw(addr, header->pages); | ||
696 | bpf_jit_binary_free(header); | ||
677 | 697 | ||
678 | kfree(prog); | 698 | free_filter: |
699 | bpf_prog_unlock_free(prog); | ||
679 | } | 700 | } |