aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/net/bpf_jit_comp.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/net/bpf_jit_comp.c')
-rw-r--r--arch/s390/net/bpf_jit_comp.c84
1 files changed, 12 insertions, 72 deletions
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
index 61e45b7c04d7..c52ac77408ca 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 */
@@ -223,37 +227,6 @@ static void bpf_jit_epilogue(struct bpf_jit *jit)
223 EMIT2(0x07fe); 227 EMIT2(0x07fe);
224} 228}
225 229
226/* Helper to find the offset of pkt_type in sk_buff
227 * Make sure its still a 3bit field starting at the MSBs within a byte.
228 */
229#define PKT_TYPE_MAX 0xe0
230static int pkt_type_offset;
231
232static int __init bpf_pkt_type_offset_init(void)
233{
234 struct sk_buff skb_probe = {
235 .pkt_type = ~0,
236 };
237 char *ct = (char *)&skb_probe;
238 int off;
239
240 pkt_type_offset = -1;
241 for (off = 0; off < sizeof(struct sk_buff); off++) {
242 if (!ct[off])
243 continue;
244 if (ct[off] == PKT_TYPE_MAX)
245 pkt_type_offset = off;
246 else {
247 /* Found non matching bit pattern, fix needed. */
248 WARN_ON_ONCE(1);
249 pkt_type_offset = -1;
250 return -1;
251 }
252 }
253 return 0;
254}
255device_initcall(bpf_pkt_type_offset_init);
256
257/* 230/*
258 * make sure we dont leak kernel information to user 231 * make sure we dont leak kernel information to user
259 */ 232 */
@@ -753,12 +726,10 @@ call_fn: /* lg %r1,<d(function)>(%r13) */
753 } 726 }
754 break; 727 break;
755 case BPF_ANC | SKF_AD_PKTTYPE: 728 case BPF_ANC | SKF_AD_PKTTYPE:
756 if (pkt_type_offset < 0)
757 goto out;
758 /* lhi %r5,0 */ 729 /* lhi %r5,0 */
759 EMIT4(0xa7580000); 730 EMIT4(0xa7580000);
760 /* ic %r5,<d(pkt_type_offset)>(%r2) */ 731 /* ic %r5,<d(pkt_type_offset)>(%r2) */
761 EMIT4_DISP(0x43502000, pkt_type_offset); 732 EMIT4_DISP(0x43502000, PKT_TYPE_OFFSET());
762 /* srl %r5,5 */ 733 /* srl %r5,5 */
763 EMIT4_DISP(0x88500000, 5); 734 EMIT4_DISP(0x88500000, 5);
764 break; 735 break;
@@ -780,38 +751,6 @@ out:
780 return -1; 751 return -1;
781} 752}
782 753
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) 754void bpf_jit_compile(struct bpf_prog *fp)
816{ 755{
817 struct bpf_binary_header *header = NULL; 756 struct bpf_binary_header *header = NULL;
@@ -850,7 +789,8 @@ void bpf_jit_compile(struct bpf_prog *fp)
850 size = prg_len + lit_len; 789 size = prg_len + lit_len;
851 if (size >= BPF_SIZE_MAX) 790 if (size >= BPF_SIZE_MAX)
852 goto out; 791 goto out;
853 header = bpf_alloc_binary(size, &jit.start); 792 header = bpf_jit_binary_alloc(size, &jit.start,
793 2, bpf_jit_fill_hole);
854 if (!header) 794 if (!header)
855 goto out; 795 goto out;
856 jit.prg = jit.mid = jit.start + prg_len; 796 jit.prg = jit.mid = jit.start + prg_len;
@@ -869,7 +809,7 @@ void bpf_jit_compile(struct bpf_prog *fp)
869 if (jit.start) { 809 if (jit.start) {
870 set_memory_ro((unsigned long)header, header->pages); 810 set_memory_ro((unsigned long)header, header->pages);
871 fp->bpf_func = (void *) jit.start; 811 fp->bpf_func = (void *) jit.start;
872 fp->jited = 1; 812 fp->jited = true;
873 } 813 }
874out: 814out:
875 kfree(addrs); 815 kfree(addrs);
@@ -884,8 +824,8 @@ void bpf_jit_free(struct bpf_prog *fp)
884 goto free_filter; 824 goto free_filter;
885 825
886 set_memory_rw(addr, header->pages); 826 set_memory_rw(addr, header->pages);
887 module_free(NULL, header); 827 bpf_jit_binary_free(header);
888 828
889free_filter: 829free_filter:
890 kfree(fp); 830 bpf_prog_unlock_free(fp);
891} 831}