Skip to content

Commit 483af46

Browse files
committed
Merge branch 'bpf-fix-verification-of-indirect-var-off-stack-access'
Andrei Matei says: ==================== bpf: fix verification of indirect var-off stack access V4 to V5: - split the test into a separate patch V3 to V4: - include a test per Eduard's request - target bpf-next per Alexei's request (patches didn't change) V2 to V3: - simplify checks for max_off (don't call check_stack_slot_within_bounds for it) - append a commit to protect against overflow in the addition of the register and the offset V1 to V2: - fix max_off calculation for access size = 0 ==================== Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Andrii Nakryiko <[email protected]>
2 parents 2146f7f + 1d38a9e commit 483af46

File tree

2 files changed

+36
-13
lines changed

2 files changed

+36
-13
lines changed

kernel/bpf/verifier.c

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6577,7 +6577,7 @@ static int check_ptr_to_map_access(struct bpf_verifier_env *env,
65776577
* The minimum valid offset is -MAX_BPF_STACK for writes, and
65786578
* -state->allocated_stack for reads.
65796579
*/
6580-
static int check_stack_slot_within_bounds(int off,
6580+
static int check_stack_slot_within_bounds(s64 off,
65816581
struct bpf_func_state *state,
65826582
enum bpf_access_type t)
65836583
{
@@ -6606,7 +6606,7 @@ static int check_stack_access_within_bounds(
66066606
struct bpf_reg_state *regs = cur_regs(env);
66076607
struct bpf_reg_state *reg = regs + regno;
66086608
struct bpf_func_state *state = func(env, reg);
6609-
int min_off, max_off;
6609+
s64 min_off, max_off;
66106610
int err;
66116611
char *err_extra;
66126612

@@ -6619,11 +6619,8 @@ static int check_stack_access_within_bounds(
66196619
err_extra = " write to";
66206620

66216621
if (tnum_is_const(reg->var_off)) {
6622-
min_off = reg->var_off.value + off;
6623-
if (access_size > 0)
6624-
max_off = min_off + access_size - 1;
6625-
else
6626-
max_off = min_off;
6622+
min_off = (s64)reg->var_off.value + off;
6623+
max_off = min_off + access_size;
66276624
} else {
66286625
if (reg->smax_value >= BPF_MAX_VAR_OFF ||
66296626
reg->smin_value <= -BPF_MAX_VAR_OFF) {
@@ -6632,15 +6629,12 @@ static int check_stack_access_within_bounds(
66326629
return -EACCES;
66336630
}
66346631
min_off = reg->smin_value + off;
6635-
if (access_size > 0)
6636-
max_off = reg->smax_value + off + access_size - 1;
6637-
else
6638-
max_off = min_off;
6632+
max_off = reg->smax_value + off + access_size;
66396633
}
66406634

66416635
err = check_stack_slot_within_bounds(min_off, state, type);
6642-
if (!err)
6643-
err = check_stack_slot_within_bounds(max_off, state, type);
6636+
if (!err && max_off > 0)
6637+
err = -EINVAL; /* out of stack access into non-negative offsets */
66446638

66456639
if (err) {
66466640
if (tnum_is_const(reg->var_off)) {

tools/testing/selftests/bpf/progs/verifier_var_off.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,35 @@ __naked void access_max_out_of_bound(void)
224224
: __clobber_all);
225225
}
226226

227+
/* Similar to the test above, but this time check the special case of a
228+
* zero-sized stack access. We used to have a bug causing crashes for zero-sized
229+
* out-of-bounds accesses.
230+
*/
231+
SEC("socket")
232+
__description("indirect variable-offset stack access, zero-sized, max out of bound")
233+
__failure __msg("invalid variable-offset indirect access to stack R1")
234+
__naked void zero_sized_access_max_out_of_bound(void)
235+
{
236+
asm volatile (" \
237+
r0 = 0; \
238+
/* Fill some stack */ \
239+
*(u64*)(r10 - 16) = r0; \
240+
*(u64*)(r10 - 8) = r0; \
241+
/* Get an unknown value */ \
242+
r1 = *(u32*)(r1 + 0); \
243+
r1 &= 63; \
244+
r1 += -16; \
245+
/* r1 is now anywhere in [-16,48) */ \
246+
r1 += r10; \
247+
r2 = 0; \
248+
r3 = 0; \
249+
call %[bpf_probe_read_kernel]; \
250+
exit; \
251+
" :
252+
: __imm(bpf_probe_read_kernel)
253+
: __clobber_all);
254+
}
255+
227256
SEC("lwt_in")
228257
__description("indirect variable-offset stack access, min out of bound")
229258
__failure __msg("invalid variable-offset indirect access to stack R2")

0 commit comments

Comments
 (0)