diff options
| author | Daniel Borkmann <daniel@iogearbox.net> | 2021-01-22 16:00:56 +0100 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2021-01-30 13:27:15 +0100 |
| commit | b98481167269b96bb60c4795dba04940202dbde3 (patch) | |
| tree | c9539f56984e8eee72170633d5eacb638465ad39 | |
| parent | 20089f3284b27eb24362725778264e4148c61f8c (diff) | |
| download | linux-b98481167269b96bb60c4795dba04940202dbde3.tar.gz linux-b98481167269b96bb60c4795dba04940202dbde3.tar.bz2 linux-b98481167269b96bb60c4795dba04940202dbde3.zip | |
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>
| -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); |
