aboutsummaryrefslogtreecommitdiff
path: root/kernel/bpf/verifier.c
diff options
context:
space:
mode:
authorAndrii Nakryiko <andrii@kernel.org>2023-12-07 10:57:36 -0800
committerAndrii Nakryiko <andrii@kernel.org>2023-12-07 13:58:14 -0800
commit483af466e4ee3326d150877ea0626e95c67a395e (patch)
treeceead968fb8ab47e59d6c55e3bc087a68736c8a8 /kernel/bpf/verifier.c
parent2146f7fe6e028a3905f0658a1a0d8ef7c115d6c1 (diff)
parent1d38a9ee81570c4bd61f557832dead4d6f816760 (diff)
Merge branch 'bpf-fix-verification-of-indirect-var-off-stack-access'
Andrei Matei says: ==================== bpf: fix verification of indirect var-off stack access V4 to V5: - split the test into a separate patch V3 to V4: - include a test per Eduard's request - target bpf-next per Alexei's request (patches didn't change) V2 to V3: - simplify checks for max_off (don't call check_stack_slot_within_bounds for it) - append a commit to protect against overflow in the addition of the register and the offset V1 to V2: - fix max_off calculation for access size = 0 ==================== Link: https://lore.kernel.org/r/20231207041150.229139-1-andreimatei1@gmail.com Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Diffstat (limited to 'kernel/bpf/verifier.c')
-rw-r--r--kernel/bpf/verifier.c20
1 files changed, 7 insertions, 13 deletions
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 45e85fb76d82..0e77bb52542d 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -6577,7 +6577,7 @@ static int check_ptr_to_map_access(struct bpf_verifier_env *env,
* The minimum valid offset is -MAX_BPF_STACK for writes, and
* -state->allocated_stack for reads.
*/
-static int check_stack_slot_within_bounds(int off,
+static int check_stack_slot_within_bounds(s64 off,
struct bpf_func_state *state,
enum bpf_access_type t)
{
@@ -6606,7 +6606,7 @@ static int check_stack_access_within_bounds(
struct bpf_reg_state *regs = cur_regs(env);
struct bpf_reg_state *reg = regs + regno;
struct bpf_func_state *state = func(env, reg);
- int min_off, max_off;
+ s64 min_off, max_off;
int err;
char *err_extra;
@@ -6619,11 +6619,8 @@ static int check_stack_access_within_bounds(
err_extra = " write to";
if (tnum_is_const(reg->var_off)) {
- min_off = reg->var_off.value + off;
- if (access_size > 0)
- max_off = min_off + access_size - 1;
- else
- max_off = min_off;
+ min_off = (s64)reg->var_off.value + off;
+ max_off = min_off + access_size;
} else {
if (reg->smax_value >= BPF_MAX_VAR_OFF ||
reg->smin_value <= -BPF_MAX_VAR_OFF) {
@@ -6632,15 +6629,12 @@ static int check_stack_access_within_bounds(
return -EACCES;
}
min_off = reg->smin_value + off;
- if (access_size > 0)
- max_off = reg->smax_value + off + access_size - 1;
- else
- max_off = min_off;
+ max_off = reg->smax_value + off + access_size;
}
err = check_stack_slot_within_bounds(min_off, state, type);
- if (!err)
- err = check_stack_slot_within_bounds(max_off, state, type);
+ if (!err && max_off > 0)
+ err = -EINVAL; /* out of stack access into non-negative offsets */
if (err) {
if (tnum_is_const(reg->var_off)) {