Skip to content

Commit 1391ecf

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 d4c4bd2 commit 1391ecf

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
@@ -5095,6 +5095,18 @@ static void check_fastcall_stack_contract(struct bpf_verifier_env *env,
50955095
}
50965096
}
50975097

5098+
static void scrub_special_slot(struct bpf_func_state *state, int spi)
5099+
{
5100+
int i;
5101+
5102+
/* regular write of data into stack destroys any spilled ptr */
5103+
state->stack[spi].spilled_ptr.type = NOT_INIT;
5104+
/* Mark slots as STACK_MISC if they belonged to spilled ptr/dynptr/iter. */
5105+
if (is_stack_slot_special(&state->stack[spi]))
5106+
for (i = 0; i < BPF_REG_SIZE; i++)
5107+
scrub_spilled_slot(&state->stack[spi].slot_type[i]);
5108+
}
5109+
50985110
/* check_stack_{read,write}_fixed_off functions track spill/fill of registers,
50995111
* stack boundary and alignment are checked in check_mem_access()
51005112
*/
@@ -5192,12 +5204,7 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
51925204
} else {
51935205
u8 type = STACK_MISC;
51945206

5195-
/* regular write of data into stack destroys any spilled ptr */
5196-
state->stack[spi].spilled_ptr.type = NOT_INIT;
5197-
/* Mark slots as STACK_MISC if they belonged to spilled ptr/dynptr/iter. */
5198-
if (is_stack_slot_special(&state->stack[spi]))
5199-
for (i = 0; i < BPF_REG_SIZE; i++)
5200-
scrub_spilled_slot(&state->stack[spi].slot_type[i]);
5207+
scrub_special_slot(state, spi);
52015208

52025209
/* when we zero initialize stack slots mark them as such */
52035210
if ((reg && register_is_null(reg)) ||
@@ -5321,8 +5328,13 @@ static int check_stack_write_var_off(struct bpf_verifier_env *env,
53215328
}
53225329
}
53235330

5324-
/* Erase all other spilled pointers. */
5325-
state->stack[spi].spilled_ptr.type = NOT_INIT;
5331+
/*
5332+
* Scrub slots if variable-offset stack write goes over spilled pointers.
5333+
* Otherwise is_spilled_reg() may == true && spilled_ptr.type == NOT_INIT
5334+
* and valid program is rejected by check_stack_read_fixed_off()
5335+
* with obscure "invalid size of register fill" message.
5336+
*/
5337+
scrub_special_slot(state, spi);
53265338

53275339
/* Update the slot type. */
53285340
new_type = STACK_MISC;

0 commit comments

Comments
 (0)