aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/net
diff options
context:
space:
mode:
authorDaniel Borkmann <dborkman@redhat.com>2014-09-08 02:04:47 -0400
committerDavid S. Miller <davem@davemloft.net>2014-09-09 19:58:56 -0400
commit738cbe72adc5c8f2016c4c68aa5162631d4f27e1 (patch)
tree4c207c0a763ea8998dddda89a7a1d9eb98866b60 /arch/s390/net
parentca777eff51f7fbaebd954e645d8ecb781a906b4a (diff)
net: bpf: consolidate JIT binary allocator
Introduced in commit 314beb9bcabf ("x86: bpf_jit_comp: secure bpf jit against spraying attacks") and later on replicated in aa2d2c73c21f ("s390/bpf,jit: address randomize and write protect jit code") for s390 architecture, write protection for BPF JIT images got added and a random start address of the JIT code, so that it's not on a page boundary anymore. Since both use a very similar allocator for the BPF binary header, we can consolidate this code into the BPF core as it's mostly JIT independant anyway. This will also allow for future archs that support DEBUG_SET_MODULE_RONX to just reuse instead of reimplementing it. JIT tested on x86_64 and s390x with BPF test suite. Signed-off-by: Daniel Borkmann <dborkman@redhat.com> Acked-by: Alexei Starovoitov <ast@plumgrid.com> Cc: Eric Dumazet <edumazet@google.com> Cc: Heiko Carstens <heiko.carstens@de.ibm.com> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/s390/net')
-rw-r--r--arch/s390/net/bpf_jit_comp.c45
1 files changed, 9 insertions, 36 deletions
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
index f2833c5b218a..b734f975c22e 100644
--- a/arch/s390/net/bpf_jit_comp.c
+++ b/arch/s390/net/bpf_jit_comp.c
@@ -5,11 +5,9 @@
5 * 5 *
6 * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> 6 * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
7 */ 7 */
8#include <linux/moduleloader.h>
9#include <linux/netdevice.h> 8#include <linux/netdevice.h>
10#include <linux/if_vlan.h> 9#include <linux/if_vlan.h>
11#include <linux/filter.h> 10#include <linux/filter.h>
12#include <linux/random.h>
13#include <linux/init.h> 11#include <linux/init.h>
14#include <asm/cacheflush.h> 12#include <asm/cacheflush.h>
15#include <asm/facility.h> 13#include <asm/facility.h>
@@ -148,6 +146,12 @@ struct bpf_jit {
148 ret; \ 146 ret; \
149}) 147})
150 148
149static 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
151static void bpf_jit_prologue(struct bpf_jit *jit) 155static void bpf_jit_prologue(struct bpf_jit *jit)
152{ 156{
153 /* Save registers and create stack frame if necessary */ 157 /* Save registers and create stack frame if necessary */
@@ -780,38 +784,6 @@ out:
780 return -1; 784 return -1;
781} 785}
782 786
783/*
784 * Note: for security reasons, bpf code will follow a randomly
785 * sized amount of illegal instructions.
786 */
787struct bpf_binary_header {
788 unsigned int pages;
789 u8 image[];
790};
791
792static 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
815void bpf_jit_compile(struct bpf_prog *fp) 787void bpf_jit_compile(struct bpf_prog *fp)
816{ 788{
817 struct bpf_binary_header *header = NULL; 789 struct bpf_binary_header *header = NULL;
@@ -850,7 +822,8 @@ void bpf_jit_compile(struct bpf_prog *fp)
850 size = prg_len + lit_len; 822 size = prg_len + lit_len;
851 if (size >= BPF_SIZE_MAX) 823 if (size >= BPF_SIZE_MAX)
852 goto out; 824 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);
854 if (!header) 827 if (!header)
855 goto out; 828 goto out;
856 jit.prg = jit.mid = jit.start + prg_len; 829 jit.prg = jit.mid = jit.start + prg_len;
@@ -884,7 +857,7 @@ void bpf_jit_free(struct bpf_prog *fp)
884 goto free_filter; 857 goto free_filter;
885 858
886 set_memory_rw(addr, header->pages); 859 set_memory_rw(addr, header->pages);
887 module_free(NULL, header); 860 bpf_jit_binary_free(header);
888 861
889free_filter: 862free_filter:
890 bpf_prog_unlock_free(fp); 863 bpf_prog_unlock_free(fp);