Skip to content

Commit be77354

Browse files
kkdwivediAlexei Starovoitov
authored andcommitted
bpf: Do write access check for kfunc and global func
When passing pointer to some map value to kfunc or global func, in verifier we are passing meta as NULL to various functions, which uses meta->raw_mode to check whether memory is being written to. Since some kfunc or global funcs may also write to memory pointers they receive as arguments, we must check for write access to memory. E.g. in some case map may be read only and this will be missed by current checks. However meta->raw_mode allows for uninitialized memory (e.g. on stack), since there is not enough info available through BTF, we must perform one call for read access (raw_mode = false), and one for write access (raw_mode = true). Fixes: e5069b9 ("bpf: Support pointers in global func args") Fixes: d583691 ("bpf: Introduce mem, size argument pair support for kfunc") Signed-off-by: Kumar Kartikeya Dwivedi <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent ebaf24c commit be77354

File tree

1 file changed

+29
-15
lines changed

1 file changed

+29
-15
lines changed

kernel/bpf/verifier.c

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4919,8 +4919,7 @@ static int check_mem_size_reg(struct bpf_verifier_env *env,
49194919
* out. Only upper bounds can be learned because retval is an
49204920
* int type and negative retvals are allowed.
49214921
*/
4922-
if (meta)
4923-
meta->msize_max_value = reg->umax_value;
4922+
meta->msize_max_value = reg->umax_value;
49244923

49254924
/* The register is SCALAR_VALUE; the access check
49264925
* happens using its boundaries.
@@ -4963,24 +4962,33 @@ static int check_mem_size_reg(struct bpf_verifier_env *env,
49634962
int check_mem_reg(struct bpf_verifier_env *env, struct bpf_reg_state *reg,
49644963
u32 regno, u32 mem_size)
49654964
{
4965+
bool may_be_null = type_may_be_null(reg->type);
4966+
struct bpf_reg_state saved_reg;
4967+
struct bpf_call_arg_meta meta;
4968+
int err;
4969+
49664970
if (register_is_null(reg))
49674971
return 0;
49684972

4969-
if (type_may_be_null(reg->type)) {
4970-
/* Assuming that the register contains a value check if the memory
4971-
* access is safe. Temporarily save and restore the register's state as
4972-
* the conversion shouldn't be visible to a caller.
4973-
*/
4974-
const struct bpf_reg_state saved_reg = *reg;
4975-
int rv;
4976-
4973+
memset(&meta, 0, sizeof(meta));
4974+
/* Assuming that the register contains a value check if the memory
4975+
* access is safe. Temporarily save and restore the register's state as
4976+
* the conversion shouldn't be visible to a caller.
4977+
*/
4978+
if (may_be_null) {
4979+
saved_reg = *reg;
49774980
mark_ptr_not_null_reg(reg);
4978-
rv = check_helper_mem_access(env, regno, mem_size, true, NULL);
4979-
*reg = saved_reg;
4980-
return rv;
49814981
}
49824982

4983-
return check_helper_mem_access(env, regno, mem_size, true, NULL);
4983+
err = check_helper_mem_access(env, regno, mem_size, true, &meta);
4984+
/* Check access for BPF_WRITE */
4985+
meta.raw_mode = true;
4986+
err = err ?: check_helper_mem_access(env, regno, mem_size, true, &meta);
4987+
4988+
if (may_be_null)
4989+
*reg = saved_reg;
4990+
4991+
return err;
49844992
}
49854993

49864994
int check_kfunc_mem_size_reg(struct bpf_verifier_env *env, struct bpf_reg_state *reg,
@@ -4989,16 +4997,22 @@ int check_kfunc_mem_size_reg(struct bpf_verifier_env *env, struct bpf_reg_state
49894997
struct bpf_reg_state *mem_reg = &cur_regs(env)[regno - 1];
49904998
bool may_be_null = type_may_be_null(mem_reg->type);
49914999
struct bpf_reg_state saved_reg;
5000+
struct bpf_call_arg_meta meta;
49925001
int err;
49935002

49945003
WARN_ON_ONCE(regno < BPF_REG_2 || regno > BPF_REG_5);
49955004

5005+
memset(&meta, 0, sizeof(meta));
5006+
49965007
if (may_be_null) {
49975008
saved_reg = *mem_reg;
49985009
mark_ptr_not_null_reg(mem_reg);
49995010
}
50005011

5001-
err = check_mem_size_reg(env, reg, regno, true, NULL);
5012+
err = check_mem_size_reg(env, reg, regno, true, &meta);
5013+
/* Check access for BPF_WRITE */
5014+
meta.raw_mode = true;
5015+
err = err ?: check_mem_size_reg(env, reg, regno, true, &meta);
50025016

50035017
if (may_be_null)
50045018
*mem_reg = saved_reg;

0 commit comments

Comments
 (0)