Skip to content

Commit 02bddee

Browse files
Alexei Starovoitovgregkh
authored andcommitted
bpf: Fix variable length stack write over spilled pointers
[ Upstream commit 4639eb9 ] Scrub slots if variable-offset stack write goes over spilled pointers. Otherwise is_spilled_reg() may == true && spilled_ptr.type == NOT_INIT and valid program is rejected by check_stack_read_fixed_off() with obscure "invalid size of register fill" message. Fixes: 01f810a ("bpf: Allow variable-offset stack access") Acked-by: Eduard Zingerman <eddyz87@gmail.com> Acked-by: Kumar Kartikeya Dwivedi <memxor@gmail.com> Link: https://lore.kernel.org/r/20260324215938.81733-1-alexei.starovoitov@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 7027e70 commit 02bddee

1 file changed

Lines changed: 20 additions & 8 deletions

File tree

kernel/bpf/verifier.c

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5241,6 +5241,18 @@ static void check_fastcall_stack_contract(struct bpf_verifier_env *env,
52415241
}
52425242
}
52435243

5244+
static void scrub_special_slot(struct bpf_func_state *state, int spi)
5245+
{
5246+
int i;
5247+
5248+
/* regular write of data into stack destroys any spilled ptr */
5249+
state->stack[spi].spilled_ptr.type = NOT_INIT;
5250+
/* Mark slots as STACK_MISC if they belonged to spilled ptr/dynptr/iter. */
5251+
if (is_stack_slot_special(&state->stack[spi]))
5252+
for (i = 0; i < BPF_REG_SIZE; i++)
5253+
scrub_spilled_slot(&state->stack[spi].slot_type[i]);
5254+
}
5255+
52445256
/* check_stack_{read,write}_fixed_off functions track spill/fill of registers,
52455257
* stack boundary and alignment are checked in check_mem_access()
52465258
*/
@@ -5338,12 +5350,7 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
53385350
} else {
53395351
u8 type = STACK_MISC;
53405352

5341-
/* regular write of data into stack destroys any spilled ptr */
5342-
state->stack[spi].spilled_ptr.type = NOT_INIT;
5343-
/* Mark slots as STACK_MISC if they belonged to spilled ptr/dynptr/iter. */
5344-
if (is_stack_slot_special(&state->stack[spi]))
5345-
for (i = 0; i < BPF_REG_SIZE; i++)
5346-
scrub_spilled_slot(&state->stack[spi].slot_type[i]);
5353+
scrub_special_slot(state, spi);
53475354

53485355
/* when we zero initialize stack slots mark them as such */
53495356
if ((reg && register_is_null(reg)) ||
@@ -5467,8 +5474,13 @@ static int check_stack_write_var_off(struct bpf_verifier_env *env,
54675474
}
54685475
}
54695476

5470-
/* Erase all other spilled pointers. */
5471-
state->stack[spi].spilled_ptr.type = NOT_INIT;
5477+
/*
5478+
* Scrub slots if variable-offset stack write goes over spilled pointers.
5479+
* Otherwise is_spilled_reg() may == true && spilled_ptr.type == NOT_INIT
5480+
* and valid program is rejected by check_stack_read_fixed_off()
5481+
* with obscure "invalid size of register fill" message.
5482+
*/
5483+
scrub_special_slot(state, spi);
54725484

54735485
/* Update the slot type. */
54745486
new_type = STACK_MISC;

0 commit comments

Comments
 (0)