mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 16:44:58 +02:00
bpf: split check_reg_sane_offset() in two parts
check_reg_sane_offset() is used when verifying operations like: dst_reg += src_reg ^ ^ | '-------- scalar '------------------- pointer To verify range for both dst_reg and src_reg. Split it in two parts: - one to check a pointer offset - another to check scalar offset This would be useful for further refactoring. Signed-off-by: Eduard Zingerman <eddyz87@gmail.com> Link: https://lore.kernel.org/r/20260212-ptrs-off-migration-v2-1-00820e4d3438@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
f632de6e19
commit
ed20a14309
|
|
@ -14426,9 +14426,9 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool check_reg_sane_offset(struct bpf_verifier_env *env,
|
||||
const struct bpf_reg_state *reg,
|
||||
enum bpf_reg_type type)
|
||||
static bool check_reg_sane_offset_scalar(struct bpf_verifier_env *env,
|
||||
const struct bpf_reg_state *reg,
|
||||
enum bpf_reg_type type)
|
||||
{
|
||||
bool known = tnum_is_const(reg->var_off);
|
||||
s64 val = reg->var_off.value;
|
||||
|
|
@ -14440,12 +14440,6 @@ static bool check_reg_sane_offset(struct bpf_verifier_env *env,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (reg->off >= BPF_MAX_VAR_OFF || reg->off <= -BPF_MAX_VAR_OFF) {
|
||||
verbose(env, "%s pointer offset %d is not allowed\n",
|
||||
reg_type_str(env, type), reg->off);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (smin == S64_MIN) {
|
||||
verbose(env, "math between %s pointer and register with unbounded min value is not allowed\n",
|
||||
reg_type_str(env, type));
|
||||
|
|
@ -14461,6 +14455,27 @@ static bool check_reg_sane_offset(struct bpf_verifier_env *env,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool check_reg_sane_offset_ptr(struct bpf_verifier_env *env,
|
||||
const struct bpf_reg_state *reg,
|
||||
enum bpf_reg_type type)
|
||||
{
|
||||
s64 smin = reg->smin_value;
|
||||
|
||||
if (reg->off >= BPF_MAX_VAR_OFF || reg->off <= -BPF_MAX_VAR_OFF) {
|
||||
verbose(env, "%s pointer offset %d is not allowed\n",
|
||||
reg_type_str(env, type), reg->off);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (smin >= BPF_MAX_VAR_OFF || smin <= -BPF_MAX_VAR_OFF) {
|
||||
verbose(env, "%s pointer offset %lld is not allowed\n",
|
||||
reg_type_str(env, type), smin);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
enum {
|
||||
REASON_BOUNDS = -1,
|
||||
REASON_TYPE = -2,
|
||||
|
|
@ -14874,8 +14889,8 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
|
|||
dst_reg->type = ptr_reg->type;
|
||||
dst_reg->id = ptr_reg->id;
|
||||
|
||||
if (!check_reg_sane_offset(env, off_reg, ptr_reg->type) ||
|
||||
!check_reg_sane_offset(env, ptr_reg, ptr_reg->type))
|
||||
if (!check_reg_sane_offset_scalar(env, off_reg, ptr_reg->type) ||
|
||||
!check_reg_sane_offset_ptr(env, ptr_reg, ptr_reg->type))
|
||||
return -EINVAL;
|
||||
|
||||
/* pointer types do not carry 32-bit bounds at the moment. */
|
||||
|
|
@ -15004,7 +15019,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
|
|||
return -EACCES;
|
||||
}
|
||||
|
||||
if (!check_reg_sane_offset(env, dst_reg, ptr_reg->type))
|
||||
if (!check_reg_sane_offset_ptr(env, dst_reg, ptr_reg->type))
|
||||
return -EINVAL;
|
||||
reg_bounds_sync(dst_reg);
|
||||
bounds_ret = sanitize_check_bounds(env, insn, dst_reg);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user