diff options
author | Daniel Borkmann <daniel@iogearbox.net> | 2021-01-22 16:00:56 +0100 |
---|---|---|
committer | Michael Bestas <mkbestas@lineageos.org> | 2022-04-19 00:51:41 +0300 |
commit | a2b6897af5af0c731fe0d4cd3dfb0c4342804b59 (patch) | |
tree | 009406c6eca8b72407c3e8cd865002ef849407cb | |
parent | b0d7bc01c2ad39eaa6e214ee7dd23f3f96ed671d (diff) |
bpf: Fix buggy rsh min/max bounds tracking
[ no upstream commit ]
Fix incorrect bounds tracking for RSH opcode. Commit f23cc643f9ba ("bpf: fix
range arithmetic for bpf map access") had a wrong assumption about min/max
bounds. The new dst_reg->min_value needs to be derived by right shifting the
max_val bounds, not min_val, and likewise new dst_reg->max_value needs to be
derived by right shifting the min_val bounds, not max_val. Later stable kernels
than 4.9 are not affected since bounds tracking was overall reworked and they
already track this similarly as in the fix.
Fixes: f23cc643f9ba ("bpf: fix range arithmetic for bpf map access")
Reported-by: Ryota Shiga (Flatt Security)
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Reviewed-by: John Fastabend <john.fastabend@gmail.com>
Cc: Josef Bacik <jbacik@fb.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Chatur27 <jasonbright2709@gmail.com>
-rw-r--r-- | kernel/bpf/verifier.c | 7 |
1 files changed, 3 insertions, 4 deletions
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 335c00209f74..78bdfbefd996 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -1732,12 +1732,11 @@ static void adjust_reg_min_max_vals(struct bpf_verifier_env *env, * unsigned shift, so make the appropriate casts. */ if (min_val < 0 || dst_reg->min_value < 0) - dst_reg->min_value = BPF_REGISTER_MIN_RANGE; + reset_reg_range_values(regs, insn->dst_reg); else - dst_reg->min_value = - (u64)(dst_reg->min_value) >> min_val; + dst_reg->min_value = (u64)(dst_reg->min_value) >> max_val; if (dst_reg->max_value != BPF_REGISTER_MAX_RANGE) - dst_reg->max_value >>= max_val; + dst_reg->max_value >>= min_val; break; default: reset_reg_range_values(regs, insn->dst_reg); |