Skip to content

Commit 443226a

Browse files
rdnashiloong
authored andcommitted
bpf: Sanity check max value for var_off stack access
OpenAnolis Bug Tracker: 0000429 commit 107c26a upstream. As discussed in [1] max value of variable offset has to be checked for overflow on stack access otherwise verifier would accept code like this: 0: (b7) r2 = 6 1: (b7) r3 = 28 2: (7a) *(u64 *)(r10 -16) = 0 3: (7a) *(u64 *)(r10 -8) = 0 4: (79) r4 = *(u64 *)(r1 +168) 5: (c5) if r4 s< 0x0 goto pc+4 R1=ctx(id=0,off=0,imm=0) R2=inv6 R3=inv28 R4=inv(id=0,umax_value=9223372036854775807,var_off=(0x0; 0x7fffffffffffffff)) R10=fp0,call_-1 fp-8=mmmmmmmm fp-16=mmmmmmmm 6: (17) r4 -= 16 7: (0f) r4 += r10 8: (b7) r5 = 8 9: (85) call bpf_getsockopt#57 10: (b7) r0 = 0 11: (95) exit , where R4 obviosly has unbounded max value. Fix it by checking that reg->smax_value is inside (-BPF_MAX_VAR_OFF; BPF_MAX_VAR_OFF) range. reg->smax_value is used instead of reg->umax_value because stack pointers are calculated using negative offset from fp. This is opposite to e.g. map access where offset must be non-negative and where umax_value is used. Also dedicated verbose logs are added for both min and max bound check failures to have diagnostics consistent with variable offset handling in check_map_access(). [1] https://marc.info/?l=linux-netdev&m=155433357510597&w=2 Fixes: 2011fcc ("bpf: Support variable offset stack access from helpers") Reported-by: Daniel Borkmann <[email protected]> Signed-off-by: Andrey Ignatov <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Signed-off-by: Ovidiu Panait <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]> Fixes: CVE-2021-34556, CVE-2021-35477 Signed-off-by: Shile Zhang <[email protected]> Acked-by: Mao Wenan <[email protected]>
1 parent e232808 commit 443226a

File tree

1 file changed

+15
-3
lines changed

1 file changed

+15
-3
lines changed

kernel/bpf/verifier.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1834,16 +1834,28 @@ static int check_stack_boundary(struct bpf_verifier_env *env, int regno,
18341834
if (meta && meta->raw_mode)
18351835
meta = NULL;
18361836

1837+
if (reg->smax_value >= BPF_MAX_VAR_OFF ||
1838+
reg->smax_value <= -BPF_MAX_VAR_OFF) {
1839+
verbose(env, "R%d unbounded indirect variable offset stack access\n",
1840+
regno);
1841+
return -EACCES;
1842+
}
18371843
min_off = reg->smin_value + reg->off;
1838-
max_off = reg->umax_value + reg->off;
1844+
max_off = reg->smax_value + reg->off;
18391845
err = __check_stack_boundary(env, regno, min_off, access_size,
18401846
zero_size_allowed);
1841-
if (err)
1847+
if (err) {
1848+
verbose(env, "R%d min value is outside of stack bound\n",
1849+
regno);
18421850
return err;
1851+
}
18431852
err = __check_stack_boundary(env, regno, max_off, access_size,
18441853
zero_size_allowed);
1845-
if (err)
1854+
if (err) {
1855+
verbose(env, "R%d max value is outside of stack bound\n",
1856+
regno);
18461857
return err;
1858+
}
18471859
}
18481860

18491861
if (meta && meta->raw_mode) {

0 commit comments

Comments
 (0)