summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Borkmann <daniel@iogearbox.net>2021-01-22 16:00:56 +0100
committerMichael Bestas <mkbestas@lineageos.org>2022-04-19 00:51:41 +0300
commita2b6897af5af0c731fe0d4cd3dfb0c4342804b59 (patch)
tree009406c6eca8b72407c3e8cd865002ef849407cb
parentb0d7bc01c2ad39eaa6e214ee7dd23f3f96ed671d (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.c7
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);