mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-16 00:34:20 +08:00
bpf: fix 32-bit ALU op verification
From: Jann Horn <jannh@google.com> [ Upstream commit468f6eafa6
] 32-bit ALU ops operate on 32-bit values and have 32-bit outputs. Adjust the verifier accordingly. Fixes:f1174f77b5
("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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
bf5ee24e87
commit
6c8e098d03
@ -1984,6 +1984,10 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* WARNING: This function does calculations on 64-bit values, but the actual
|
||||
* execution may occur on 32-bit values. Therefore, things like bitshifts
|
||||
* need extra checks in the 32-bit case.
|
||||
*/
|
||||
static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
|
||||
struct bpf_insn *insn,
|
||||
struct bpf_reg_state *dst_reg,
|
||||
@ -1994,12 +1998,8 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
|
||||
bool src_known, dst_known;
|
||||
s64 smin_val, smax_val;
|
||||
u64 umin_val, umax_val;
|
||||
u64 insn_bitness = (BPF_CLASS(insn->code) == BPF_ALU64) ? 64 : 32;
|
||||
|
||||
if (BPF_CLASS(insn->code) != BPF_ALU64) {
|
||||
/* 32-bit ALU ops are (32,32)->64 */
|
||||
coerce_reg_to_size(dst_reg, 4);
|
||||
coerce_reg_to_size(&src_reg, 4);
|
||||
}
|
||||
smin_val = src_reg.smin_value;
|
||||
smax_val = src_reg.smax_value;
|
||||
umin_val = src_reg.umin_value;
|
||||
@ -2135,9 +2135,9 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
|
||||
__update_reg_bounds(dst_reg);
|
||||
break;
|
||||
case BPF_LSH:
|
||||
if (umax_val > 63) {
|
||||
/* Shifts greater than 63 are undefined. This includes
|
||||
* shifts by a negative number.
|
||||
if (umax_val >= insn_bitness) {
|
||||
/* Shifts greater than 31 or 63 are undefined.
|
||||
* This includes shifts by a negative number.
|
||||
*/
|
||||
mark_reg_unknown(regs, insn->dst_reg);
|
||||
break;
|
||||
@ -2163,9 +2163,9 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
|
||||
__update_reg_bounds(dst_reg);
|
||||
break;
|
||||
case BPF_RSH:
|
||||
if (umax_val > 63) {
|
||||
/* Shifts greater than 63 are undefined. This includes
|
||||
* shifts by a negative number.
|
||||
if (umax_val >= insn_bitness) {
|
||||
/* Shifts greater than 31 or 63 are undefined.
|
||||
* This includes shifts by a negative number.
|
||||
*/
|
||||
mark_reg_unknown(regs, insn->dst_reg);
|
||||
break;
|
||||
@ -2201,6 +2201,12 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
|
||||
break;
|
||||
}
|
||||
|
||||
if (BPF_CLASS(insn->code) != BPF_ALU64) {
|
||||
/* 32-bit ALU ops are (32,32)->32 */
|
||||
coerce_reg_to_size(dst_reg, 4);
|
||||
coerce_reg_to_size(&src_reg, 4);
|
||||
}
|
||||
|
||||
__reg_deduce_bounds(dst_reg);
|
||||
__reg_bound_offset(dst_reg);
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user