Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'bpf-simplify-checking-size-of-helper-accesses'

Andrei Matei says:

====================
bpf: Simplify checking size of helper accesses

v3->v4:
- kept only the minimal change, undoing debatable changes (Andrii)
- dropped the second patch from before, with changes to the error
message (Andrii)
- extracted the new test into a separate patch (Andrii)
- added Acked by Andrii

v2->v3:
- split the error-logging function to a separate patch (Andrii)
- make the error buffers smaller (Andrii)
- include size of memory region for PTR_TO_MEM (Andrii)
- nits from Andrii and Eduard

v1->v2:
- make the error message include more info about the context of the
zero-sized access (Andrii)
====================

Link: https://lore.kernel.org/r/20231221232225.568730-1-andreimatei1@gmail.com
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>

+46 -11
+4 -6
kernel/bpf/verifier.c
··· 7279 7279 return -EACCES; 7280 7280 } 7281 7281 7282 - if (reg->umin_value == 0) { 7283 - err = check_helper_mem_access(env, regno - 1, 0, 7284 - zero_size_allowed, 7285 - meta); 7286 - if (err) 7287 - return err; 7282 + if (reg->umin_value == 0 && !zero_size_allowed) { 7283 + verbose(env, "R%d invalid zero-sized read: u64=[%lld,%lld]\n", 7284 + regno, reg->umin_value, reg->umax_value); 7285 + return -EACCES; 7288 7286 } 7289 7287 7290 7288 if (reg->umax_value >= BPF_MAX_VAR_SIZ) {
+41 -4
tools/testing/selftests/bpf/progs/verifier_helper_value_access.c
··· 89 89 : __clobber_all); 90 90 } 91 91 92 + /* Call a function taking a pointer and a size which doesn't allow the size to 93 + * be zero (i.e. bpf_trace_printk() declares the second argument to be 94 + * ARG_CONST_SIZE, not ARG_CONST_SIZE_OR_ZERO). We attempt to pass zero for the 95 + * size and expect to fail. 96 + */ 92 97 SEC("tracepoint") 93 98 __description("helper access to map: empty range") 94 - __failure __msg("invalid access to map value, value_size=48 off=0 size=0") 99 + __failure __msg("R2 invalid zero-sized read: u64=[0,0]") 95 100 __naked void access_to_map_empty_range(void) 96 101 { 97 102 asm volatile (" \ ··· 111 106 r2 = 0; \ 112 107 call %[bpf_trace_printk]; \ 113 108 l0_%=: exit; \ 109 + " : 110 + : __imm(bpf_map_lookup_elem), 111 + __imm(bpf_trace_printk), 112 + __imm_addr(map_hash_48b) 113 + : __clobber_all); 114 + } 115 + 116 + /* Like the test above, but this time the size register is not known to be zero; 117 + * its lower-bound is zero though, which is still unacceptable. 118 + */ 119 + SEC("tracepoint") 120 + __description("helper access to map: possibly-empty ange") 121 + __failure __msg("R2 invalid zero-sized read: u64=[0,4]") 122 + __naked void access_to_map_possibly_empty_range(void) 123 + { 124 + asm volatile (" \ 125 + r2 = r10; \ 126 + r2 += -8; \ 127 + r1 = 0; \ 128 + *(u64*)(r2 + 0) = r1; \ 129 + r1 = %[map_hash_48b] ll; \ 130 + call %[bpf_map_lookup_elem]; \ 131 + if r0 == 0 goto l0_%=; \ 132 + r1 = r0; \ 133 + /* Read an unknown value */ \ 134 + r7 = *(u64*)(r0 + 0); \ 135 + /* Make it small and positive, to avoid other errors */ \ 136 + r7 &= 4; \ 137 + r2 = 0; \ 138 + r2 += r7; \ 139 + call %[bpf_trace_printk]; \ 140 + l0_%=: exit; \ 114 141 " : 115 142 : __imm(bpf_map_lookup_elem), 116 143 __imm(bpf_trace_printk), ··· 258 221 259 222 SEC("tracepoint") 260 223 __description("helper access to adjusted map (via const imm): empty range") 261 - __failure __msg("invalid access to map value, value_size=48 off=4 size=0") 224 + __failure __msg("R2 invalid zero-sized read") 262 225 __naked void via_const_imm_empty_range(void) 263 226 { 264 227 asm volatile (" \ ··· 423 386 424 387 SEC("tracepoint") 425 388 __description("helper access to adjusted map (via const reg): empty range") 426 - __failure __msg("R1 min value is outside of the allowed memory range") 389 + __failure __msg("R2 invalid zero-sized read") 427 390 __naked void via_const_reg_empty_range(void) 428 391 { 429 392 asm volatile (" \ ··· 593 556 594 557 SEC("tracepoint") 595 558 __description("helper access to adjusted map (via variable): empty range") 596 - __failure __msg("R1 min value is outside of the allowed memory range") 559 + __failure __msg("R2 invalid zero-sized read") 597 560 __naked void map_via_variable_empty_range(void) 598 561 { 599 562 asm volatile (" \
+1 -1
tools/testing/selftests/bpf/progs/verifier_raw_stack.c
··· 64 64 65 65 SEC("tc") 66 66 __description("raw_stack: skb_load_bytes, zero len") 67 - __failure __msg("invalid zero-sized read") 67 + __failure __msg("R4 invalid zero-sized read: u64=[0,0]") 68 68 __naked void skb_load_bytes_zero_len(void) 69 69 { 70 70 asm volatile (" \