diff options
author | Sami Tolvanen <samitolvanen@google.com> | 2019-09-04 14:08:16 -0700 |
---|---|---|
committer | Michael Bestas <mkbestas@lineageos.org> | 2022-04-19 00:51:53 +0300 |
commit | 1f459d731993dcaa501ec8fd6b03ff43f42bf108 (patch) | |
tree | fbcc3315bcbd81cf9b5b2cf3e3d6882d84b8fa89 /kernel/bpf/core.c | |
parent | c6da67a69b16e2f7ad9127b5f047d10b3c8a20b3 (diff) |
ANDROID: bpf: validate bpf_func when BPF_JIT is enabled with CFI
With CONFIG_BPF_JIT, the kernel makes indirect calls to dynamically
generated code, which the compile-time Control-Flow Integrity (CFI)
checking cannot validate. This change adds basic sanity checking to
ensure we are jumping to a valid location, which narrows down the
attack surface on the stored pointer.
In addition, this change adds a weak arch_bpf_jit_check_func function,
which architectures that implement BPF JIT can override to perform
additional validation, such as verifying that the pointer points to
the correct memory region.
Bug: 140377409
Change-Id: I8ebac6637ab6bd9db44716b1c742add267298669
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
Diffstat (limited to 'kernel/bpf/core.c')
-rw-r--r-- | kernel/bpf/core.c | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index 6e407cd56cc4..95ffe1fac0bf 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c @@ -257,6 +257,14 @@ static void bpf_jit_uncharge_modmem(u32 pages) atomic_long_sub(pages, &bpf_jit_current); } +#if IS_ENABLED(CONFIG_BPF_JIT) && IS_ENABLED(CONFIG_CFI_CLANG) +bool __weak arch_bpf_jit_check_func(const struct bpf_prog *prog) +{ + return true; +} +EXPORT_SYMBOL(arch_bpf_jit_check_func); +#endif + struct bpf_binary_header * bpf_jit_binary_alloc(unsigned int proglen, u8 **image_ptr, unsigned int alignment, @@ -283,6 +291,7 @@ bpf_jit_binary_alloc(unsigned int proglen, u8 **image_ptr, /* Fill space with illegal/arch-dep instructions. */ bpf_fill_ill_insns(hdr, size); + bpf_jit_set_header_magic(hdr); hdr->pages = pages; hole = min_t(unsigned int, size - (proglen + sizeof(*hdr)), PAGE_SIZE - sizeof(*hdr)); |