Skip to content

Commit 468f6ea

Browse files
thejhborkmann
authored andcommitted
bpf: fix 32-bit ALU op verification
32-bit ALU ops operate on 32-bit values and have 32-bit outputs. Adjust the verifier accordingly. Fixes: f1174f7 ("bpf/verifier: rework value tracking") Signed-off-by: Jann Horn <jannh@google.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
1 parent 0c17d1d commit 468f6ea

File tree

1 file changed

+17
-11
lines changed

1 file changed

+17
-11
lines changed

kernel/bpf/verifier.c

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2017,6 +2017,10 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
20172017
return 0;
20182018
}
20192019

2020+
/* WARNING: This function does calculations on 64-bit values, but the actual
2021+
* execution may occur on 32-bit values. Therefore, things like bitshifts
2022+
* need extra checks in the 32-bit case.
2023+
*/
20202024
static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
20212025
struct bpf_insn *insn,
20222026
struct bpf_reg_state *dst_reg,
@@ -2027,12 +2031,8 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
20272031
bool src_known, dst_known;
20282032
s64 smin_val, smax_val;
20292033
u64 umin_val, umax_val;
2034+
u64 insn_bitness = (BPF_CLASS(insn->code) == BPF_ALU64) ? 64 : 32;
20302035

2031-
if (BPF_CLASS(insn->code) != BPF_ALU64) {
2032-
/* 32-bit ALU ops are (32,32)->64 */
2033-
coerce_reg_to_size(dst_reg, 4);
2034-
coerce_reg_to_size(&src_reg, 4);
2035-
}
20362036
smin_val = src_reg.smin_value;
20372037
smax_val = src_reg.smax_value;
20382038
umin_val = src_reg.umin_value;
@@ -2168,9 +2168,9 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
21682168
__update_reg_bounds(dst_reg);
21692169
break;
21702170
case BPF_LSH:
2171-
if (umax_val > 63) {
2172-
/* Shifts greater than 63 are undefined. This includes
2173-
* shifts by a negative number.
2171+
if (umax_val >= insn_bitness) {
2172+
/* Shifts greater than 31 or 63 are undefined.
2173+
* This includes shifts by a negative number.
21742174
*/
21752175
mark_reg_unknown(env, regs, insn->dst_reg);
21762176
break;
@@ -2196,9 +2196,9 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
21962196
__update_reg_bounds(dst_reg);
21972197
break;
21982198
case BPF_RSH:
2199-
if (umax_val > 63) {
2200-
/* Shifts greater than 63 are undefined. This includes
2201-
* shifts by a negative number.
2199+
if (umax_val >= insn_bitness) {
2200+
/* Shifts greater than 31 or 63 are undefined.
2201+
* This includes shifts by a negative number.
22022202
*/
22032203
mark_reg_unknown(env, regs, insn->dst_reg);
22042204
break;
@@ -2234,6 +2234,12 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
22342234
break;
22352235
}
22362236

2237+
if (BPF_CLASS(insn->code) != BPF_ALU64) {
2238+
/* 32-bit ALU ops are (32,32)->32 */
2239+
coerce_reg_to_size(dst_reg, 4);
2240+
coerce_reg_to_size(&src_reg, 4);
2241+
}
2242+
22372243
__reg_deduce_bounds(dst_reg);
22382244
__reg_bound_offset(dst_reg);
22392245
return 0;

0 commit comments

Comments
 (0)