Skip to content

Commit d45781c

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 cb2c1f3 commit d45781c

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
@@ -4724,6 +4724,18 @@ static void check_fastcall_stack_contract(struct bpf_verifier_env *env,
47244724
}
47254725
}
47264726

4727+
static void scrub_special_slot(struct bpf_func_state *state, int spi)
4728+
{
4729+
int i;
4730+
4731+
/* regular write of data into stack destroys any spilled ptr */
4732+
state->stack[spi].spilled_ptr.type = NOT_INIT;
4733+
/* Mark slots as STACK_MISC if they belonged to spilled ptr/dynptr/iter. */
4734+
if (is_stack_slot_special(&state->stack[spi]))
4735+
for (i = 0; i < BPF_REG_SIZE; i++)
4736+
scrub_spilled_slot(&state->stack[spi].slot_type[i]);
4737+
}
4738+
47274739
/* check_stack_{read,write}_fixed_off functions track spill/fill of registers,
47284740
* stack boundary and alignment are checked in check_mem_access()
47294741
*/
@@ -4809,12 +4821,7 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
48094821
} else {
48104822
u8 type = STACK_MISC;
48114823

4812-
/* regular write of data into stack destroys any spilled ptr */
4813-
state->stack[spi].spilled_ptr.type = NOT_INIT;
4814-
/* Mark slots as STACK_MISC if they belonged to spilled ptr/dynptr/iter. */
4815-
if (is_stack_slot_special(&state->stack[spi]))
4816-
for (i = 0; i < BPF_REG_SIZE; i++)
4817-
scrub_spilled_slot(&state->stack[spi].slot_type[i]);
4824+
scrub_special_slot(state, spi);
48184825

48194826
/* only mark the slot as written if all 8 bytes were written
48204827
* otherwise read propagation may incorrectly stop too soon
@@ -4949,8 +4956,13 @@ static int check_stack_write_var_off(struct bpf_verifier_env *env,
49494956
}
49504957
}
49514958

4952-
/* Erase all other spilled pointers. */
4953-
state->stack[spi].spilled_ptr.type = NOT_INIT;
4959+
/*
4960+
* Scrub slots if variable-offset stack write goes over spilled pointers.
4961+
* Otherwise is_spilled_reg() may == true && spilled_ptr.type == NOT_INIT
4962+
* and valid program is rejected by check_stack_read_fixed_off()
4963+
* with obscure "invalid size of register fill" message.
4964+
*/
4965+
scrub_special_slot(state, spi);
49544966

49554967
/* Update the slot type. */
49564968
new_type = STACK_MISC;

0 commit comments

Comments
 (0)