[v3,2/2] arm64/bpf: don't allocate BPF JIT programs in module memory

Message ID 20181123094152.21368-3-ard.biesheuvel@linaro.org
State New
Headers show
  • bpf: permit JIT allocations to be served outside the module region
Related show

Commit Message

Ard Biesheuvel Nov. 23, 2018, 9:41 a.m.
The arm64 module region is a 128 MB region that is kept close to
the core kernel, in order to ensure that relative branches are
always in range. So using the same region for programs that do
not have this restriction is wasteful, and preferably avoided.

Now that the core BPF JIT code permits the alloc/free routines to
be overridden, implement them by vmalloc()/vfree() calls from a
dedicated 128 MB region set aside for BPF programs. This ensures
that BPF programs are still in branching range of each other, which
is something the JIT currently depends upon (and is not guaranteed
when using module_alloc() on KASLR kernels like we do currently).
It also ensures that placement of BPF programs does not correlate
with the placement of the core kernel or modules, making it less
likely that leaking the former will reveal the latter.

This also solves an issue under KASAN, where shadow memory is
needlessly allocated for all BPF programs (which don't require KASAN
shadow pages since they are not KASAN instrumented)

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

 arch/arm64/include/asm/memory.h  |  3 +++
 arch/arm64/include/asm/pgtable.h |  2 +-
 arch/arm64/net/bpf_jit_comp.c    | 13 +++++++++++++
 3 files changed, 17 insertions(+), 1 deletion(-)



kbuild test robot Nov. 26, 2018, 2:22 a.m. | #1
Hi Ard,

I love your patch! Perhaps something to improve:

[auto build test WARNING on arm64/for-next/core]
[also build test WARNING on v4.20-rc4 next-20181123]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Ard-Biesheuvel/bpf-permit-JIT-allocations-to-be-served-outside-the-module-region/20181126-024110
base:   https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core
config: x86_64-allmodconfig (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All warnings (new ones prefixed by >>):

   include/linux/slab.h:332:43: warning: dubious: x & !y
   kernel/bpf/core.c:612:6: warning: symbol 'bpf_jit_alloc_exec' was not declared. Should it be static?
>> kernel/bpf/core.c:619:24: warning: incorrect type in argument 1 (different modifiers)

   kernel/bpf/core.c:619:24:    expected void *module_region
   kernel/bpf/core.c:619:24:    got void const *addr
   kernel/bpf/core.c:617:13: warning: symbol 'bpf_jit_free_exec' was not declared. Should it be static?
   include/linux/slab.h:332:43: warning: dubious: x & !y
   kernel/bpf/core.c:1608:9: warning: incorrect type in argument 1 (different address spaces)
   kernel/bpf/core.c:1608:9:    expected struct callback_head *head
   kernel/bpf/core.c:1608:9:    got struct callback_head [noderef] <asn:4>*<noident>
   include/linux/slab.h:332:43: warning: dubious: x & !y
   kernel/bpf/core.c:1682:44: warning: incorrect type in initializer (different address spaces)
   kernel/bpf/core.c:1682:44:    expected struct bpf_prog_array_item *item
   kernel/bpf/core.c:1682:44:    got struct bpf_prog_array_item [noderef] <asn:4>*<noident>
   kernel/bpf/core.c:1706:26: warning: incorrect type in assignment (different address spaces)
   kernel/bpf/core.c:1706:26:    expected struct bpf_prog_array_item *existing
   kernel/bpf/core.c:1706:26:    got struct bpf_prog_array_item [noderef] <asn:4>*<noident>
   kernel/bpf/core.c:1740:26: warning: incorrect type in assignment (different address spaces)
   kernel/bpf/core.c:1740:26:    expected struct bpf_prog_array_item *[assigned] existing
   kernel/bpf/core.c:1740:26:    got struct bpf_prog_array_item [noderef] <asn:4>*<noident>
   include/trace/events/xdp.h:28:1: warning: Using plain integer as NULL pointer
   include/trace/events/xdp.h:53:1: warning: Using plain integer as NULL pointer
   include/trace/events/xdp.h:111:1: warning: Using plain integer as NULL pointer
   include/trace/events/xdp.h:126:1: warning: Using plain integer as NULL pointer
   include/trace/events/xdp.h:161:1: warning: Using plain integer as NULL pointer
   include/trace/events/xdp.h:196:1: warning: Using plain integer as NULL pointer
   include/trace/events/xdp.h:231:1: warning: Using plain integer as NULL pointer
   kernel/bpf/core.c:999:18: warning: Initializer entry defined twice
   kernel/bpf/core.c:1001:17:   also defined here
   kernel/bpf/core.c: In function 'bpf_jit_free_exec':
   kernel/bpf/core.c:619:17: warning: passing argument 1 of 'module_memfree' discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
   In file included from kernel/bpf/core.c:28:0:
   include/linux/moduleloader.h:30:6: note: expected 'void *' but argument is of type 'const void *'
    void module_memfree(void *module_region);

vim +619 kernel/bpf/core.c

ede95a63b Daniel Borkmann 2018-10-23  611  
eff59cbcb Ard Biesheuvel  2018-11-23 @612  void *__weak bpf_jit_alloc_exec(unsigned long size)
eff59cbcb Ard Biesheuvel  2018-11-23  613  {
eff59cbcb Ard Biesheuvel  2018-11-23  614  	return module_alloc(size);
eff59cbcb Ard Biesheuvel  2018-11-23  615  }
eff59cbcb Ard Biesheuvel  2018-11-23  616  
eff59cbcb Ard Biesheuvel  2018-11-23  617  void __weak bpf_jit_free_exec(const void *addr)
eff59cbcb Ard Biesheuvel  2018-11-23  618  {
eff59cbcb Ard Biesheuvel  2018-11-23 @619  	module_memfree(addr);
eff59cbcb Ard Biesheuvel  2018-11-23  620  }
eff59cbcb Ard Biesheuvel  2018-11-23  621  

:::::: The code at line 619 was first introduced by commit
:::::: eff59cbcb348cb3df3fd41aba28df574c6cf7c27 bpf: add __weak hook for allocating executable memory

:::::: TO: Ard Biesheuvel <ard.biesheuvel@linaro.org>
:::::: CC: 0day robot <lkp@intel.com>

0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation


diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index b96442960aea..506e319da98f 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -69,6 +69,9 @@ 
+#define BPF_JIT_REGION_SIZE	(SZ_128M)
 #define KERNEL_START      _text
 #define KERNEL_END        _end
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 50b1ef8584c0..9db98a4cd9b4 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -31,7 +31,7 @@ 
  *	and fixed mappings
 #define vmemmap			((struct page *)VMEMMAP_START - (memstart_addr >> PAGE_SHIFT))
diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
index a6fdaea07c63..298beba29fa5 100644
--- a/arch/arm64/net/bpf_jit_comp.c
+++ b/arch/arm64/net/bpf_jit_comp.c
@@ -940,3 +940,16 @@  struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
 					   tmp : orig_prog);
 	return prog;
+void *bpf_jit_alloc_exec(unsigned long size)
+	return __vmalloc_node_range(size, PAGE_SIZE, BPF_JIT_REGION_BASE,
+				    __builtin_return_address(0));
+void bpf_jit_free_exec(const void *addr)
+	return vfree(addr);