bpf: add support for KASAN checks in JITed programs#12754
bpf: add support for KASAN checks in JITed programs#12754kernel-patches-daemon-bpf[bot] wants to merge 10 commits into
Conversation
|
Upstream branch: 36ffa86 |
f42b070 to
76af7b1
Compare
|
Upstream branch: c3d5ef2 |
4b6e451 to
30181fc
Compare
76af7b1 to
294813d
Compare
|
Upstream branch: a455304 |
30181fc to
1be85cb
Compare
294813d to
3d40a7b
Compare
|
Upstream branch: b1d4514 |
1be85cb to
9c7f198
Compare
3d40a7b to
320974b
Compare
|
Upstream branch: 30f77a0 |
9c7f198 to
a23483a
Compare
320974b to
a8517a2
Compare
|
Upstream branch: e821c22 |
a23483a to
55eb594
Compare
a8517a2 to
386cc3c
Compare
|
Upstream branch: 77f02c9 |
55eb594 to
d6c05bb
Compare
386cc3c to
ded8f8a
Compare
When the verifier patches an ebpf program with bpf_patch_insn_data, it then calls adjust_insn_aux_data to make sure that insn_aux_data takes into account the newly inserted patch. Some of the data offset is pretty straightforward to deduce, it is for example the case for indirect_target, as any patch affecting indirect calls will systematically move the original instruction to the end of the new patch. In order to introduce KASAN support for eBPF JIT, we need to mark any load/store instruction that accesses non-stack memory, but updating this new marking after a patch is not as straightforward as for indirect calls: the original BPF_ST/BPF_STX/BPF_LDX can be at the beginning, at the end or somewhere in the middle of the new patch: we then need some additional info to properly update this marking. Add a new parameter to bpf_patch_insn_data and adjust_insn_aux_data to convey the info about the new location in the patch of the original instruction. This info does not always make sense depending on the generated patch (eg, some bpf helpers being inlined by the verifier, and so turned into multiple new instructions without any remaining BPF_CALL), the parameter can then be set to -1. It will be used in next patches to properly handle insn_aux_data adjustment for the new KASAN instrumentation Signed-off-by: Alexis Lothoré (eBPF Foundation) <alexis.lothore@bootlin.com>
In order to prepare to emit KASAN checks in JITed programs, JIT compilers need to be aware about whether some load/store instructions are targeting the bpf program stack, as those should not be monitored (we already have guard pages for that, and it is difficult anyway to correctly monitor any kind of data passed on stack). To support this need, make the BPF verifier mark the instructions depending on whether they could access or not memory other than stack. As different states in the verifier could lead to different memory types for the same access, just marking an instruction as accessing stack only is not enough (it could be some other memory type in another verifier state), so the algorithm rather sets by default any load/store instruction as stack only, and if _any_ state leads to any memory access type other than PTR_TO_STACK, it overrides this setting. It also takes care about shifting back the instruction marking in adjust_insn_aux_data if the verifier patches instructions. However, if the verifier generates new BPF_ST/BPF_STX/BPF_LDX while patching some instructions, those new ones are systematically marked as non-stack-accessing: this may over-instrument a few memory accessing instructions, but it allows making sure that we will not miss accidentally any. Signed-off-by: Alexis Lothoré (eBPF Foundation) <alexis.lothore@bootlin.com>
Add a new Kconfig option CONFIG_BPF_JIT_KASAN that automatically enables generic KASAN (Kernel Address SANitizer) memory access checks for JIT-compiled BPF programs as well, when both KASAN (and more specifically, generic KASAN with KASAN_VMALLOC) and JIT compiler are enabled. This new Kconfig is not a user selectable one: it is either automatically enabled if KASAN is enabled on a compatible platform. When enabled, the JIT compiler will emit shadow memory checks before memory loads and stores to detect use-after-free or out-of-bounds accesses at runtime. The option is gated behind HAVE_EBPF_JIT_KASAN, as it needs proper arch-specific implementation. Signed-off-by: Alexis Lothoré (eBPF Foundation) <alexis.lothore@bootlin.com>
Add the emit_kasan_check() function that emits KASAN shadow memory
checks before memory accesses in JIT-compiled BPF programs. The
implementation relies on the existing __asan_{load,store}X functions
from KASAN subsystem. The helper:
- ensures that the kasan instrumention is actually needed: if the
instruction being processed accesses the program stack, we skip the
instrumentation, as those accesses are already protected with page
guards
- saves registers. This includes caller-saved registers, but also
temporary registers, as those were possibly used by the
affected program. Theoretically, r10 and r11 should be saved as well,
but the number of called function and their scope being limited, they
are skipped for the sake of reducing the overhead
- computes the accessed address and stores it in %rdi
- calls the relevant function, depending on the instruction being a load
or a store, and the size of the access.
- restores registers
The special care needed when inserting this instrumentation comes at the
cost of a non negligeable increase in JITed code size. For example, a
bare
mov 0x0(%si),rbx # Load in rbx content at address stored in rsi
becomes
push %rax
push %rcx
push %rdx
push %rsi
push %rdi
push %r8
push %r9
mov %rsi,%rdi
call 0xffffffff81da0a60 <__asan_load8>
pop %r9
pop %r8
pop %rdi
pop %rsi
pop %rdx
pop %rcx
pop %rax
mov 0x0(%rsi),rbx
Signed-off-by: Alexis Lothoré (eBPF Foundation) <alexis.lothore@bootlin.com>
In order to prepare for KASAN checks insertion before every memory-related load or store, group all BPF_ST instructions that indeed access memory in a single helper to allow instrumenting those in one call, rather than having to instrument all cases individually. Signed-off-by: Alexis Lothoré (eBPF Foundation) <alexis.lothore@bootlin.com>
Insert KASAN shadow memory checks before memory load and store operations in JIT-compiled BPF programs. This helps detect memory safety bugs such as use-after-free and out-of-bounds accesses at runtime. The main instructions being targeted are BPF_ST, BPF_STX and BPF_LDX, but not all of them are being instrumented: - if the load/store instruction is in fact accessing the program stack, emit_kasan_check silently skips the instrumentation, as we can already benefit from guard pages to monitor stack accesses. - if the load/store instruction is a BPF_PROBE_MEM or a BPF_PROBE_ATOMIC instruction, we do not instrument it, as the passed address can fault (hence the custom fault management with BPF_PROBE_XXX instructions), and so the corresponding kasan check could fault as well. Signed-off-by: Alexis Lothoré (eBPF Foundation) <alexis.lothore@bootlin.com>
Mark x86 as supporting KASAN checks in JITed programs so that the corresponding JIT compiler inserts checks on the translated instructions. Signed-off-by: Alexis Lothoré (eBPF Foundation) <alexis.lothore@bootlin.com>
|
Upstream branch: 520d7d7 |
Add two simple helpers to allow checking whether KASAN for eBPF tests should be executed: - one helper to check if BPF_JIT_KASAN is enabled in kernel configuration - one helper to check if the kernel is running with kasan_multi_shot (otherwise only the first test will be able to trigger a report) Signed-off-by: Alexis Lothoré (eBPF Foundation) <alexis.lothore@bootlin.com>
Move set_bpf_jit_harden to testing helpers so that other selftests can change the hardening configuration without re-implementing a helper. Signed-off-by: Alexis Lothoré (eBPF Foundation) <alexis.lothore@bootlin.com>
Add a basic KASAN test runner that loads and test-run programs that can trigger memory management bugs. The test captures kernel logs and ensure that the expected KASAN splat is emitted by searching for the corresponding first lines in the report, hence validated that the needed instrumentation has been inserted by the JIT compiler before the relevant memory accesses. To allow each test to trigger the expected report, the kernel must run with the kasan_multi_shot configuration. The runner covers different cases and settings: in the nominal case, it validates kasan reports on basic instructions (on all supported accesses sizes) but also when report _should not_ be emitted (eg: for accesses on program stack). The runner also comes with a few specialized tests that are then not executed for all sizes/locations: - specific atomic ops - test for instructions involving different verifier states, with some states flagging memory as stack, and other states as non-stack memory - tests that validate the stack marking shifting when a patch is emitted by the verifier (zext/rnd_hi32, constant blindind) A few of those tests depends on cpuv4 (load_acquire and store_release). # ./test_progs -a kasan #165/1 kasan/st_1_not_on_stack:OK #165/2 kasan/st_1_on_stack:OK #165/3 kasan/st_2_not_on_stack:OK #165/4 kasan/st_2_on_stack:OK #165/5 kasan/st_4_not_on_stack:OK #165/6 kasan/st_4_on_stack:OK #165/7 kasan/st_8_not_on_stack:OK #165/8 kasan/st_8_on_stack:OK #165/9 kasan/stx_1_not_on_stack:OK #165/10 kasan/stx_1_on_stack:OK #165/11 kasan/stx_2_not_on_stack:OK #165/12 kasan/stx_2_on_stack:OK #165/13 kasan/stx_4_not_on_stack:OK #165/14 kasan/stx_4_on_stack:OK #165/15 kasan/stx_8_not_on_stack:OK #165/16 kasan/stx_8_on_stack:OK #165/17 kasan/ldx_1_not_on_stack:OK #165/18 kasan/ldx_1_on_stack:OK #165/19 kasan/ldx_2_not_on_stack:OK #165/20 kasan/ldx_2_on_stack:OK #165/21 kasan/ldx_4_not_on_stack:OK #165/22 kasan/ldx_4_on_stack:OK #165/23 kasan/ldx_8_not_on_stack:OK #165/24 kasan/ldx_8_on_stack:OK #165/25 kasan/simple_atomic_4_not_on_stack:OK #165/26 kasan/simple_atomic_4_on_stack:OK #165/27 kasan/simple_atomic_8_not_on_stack:OK #165/28 kasan/simple_atomic_8_on_stack:OK #165/29 kasan/load_acquire_1_not_on_stack:SKIP #165/30 kasan/load_acquire_1_on_stack:SKIP #165/31 kasan/load_acquire_2_not_on_stack:SKIP #165/32 kasan/load_acquire_2_on_stack:SKIP #165/33 kasan/load_acquire_4_not_on_stack:SKIP #165/34 kasan/load_acquire_4_on_stack:SKIP #165/35 kasan/load_acquire_8_not_on_stack:SKIP #165/36 kasan/load_acquire_8_on_stack:SKIP #165/37 kasan/store_release_1_not_on_stack:SKIP #165/38 kasan/store_release_1_on_stack:SKIP #165/39 kasan/store_release_2_not_on_stack:SKIP #165/40 kasan/store_release_2_on_stack:SKIP #165/41 kasan/store_release_4_not_on_stack:SKIP #165/42 kasan/store_release_4_on_stack:SKIP #165/43 kasan/store_release_8_not_on_stack:SKIP #165/44 kasan/store_release_8_on_stack:SKIP #165/45 kasan/ldx_patched:OK #165/46 kasan/ldx_patched_on_stack:OK #165/47 kasan/verifier_paths_stack_and_non_stack:OK #165/48 kasan/st_blinded:OK #165 kasan:OK (SKIP: 16/48) Summary: 1/32 PASSED, 16 SKIPPED, 0 FAILED Signed-off-by: Alexis Lothoré (eBPF Foundation) <alexis.lothore@bootlin.com>
d6c05bb to
6eed410
Compare
Pull request for series with
subject: bpf: add support for KASAN checks in JITed programs
version: 5
url: https://patchwork.kernel.org/project/netdevbpf/list/?series=1124557