Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpf: Some fixes for nullness elision #4937

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 21 additions & 8 deletions kernel/bpf/verifier.c
Original file line number Diff line number Diff line change
Expand Up @@ -9149,10 +9149,11 @@ static int check_reg_const_str(struct bpf_verifier_env *env,
return 0;
}

/* Returns constant key value if possible, else negative error */
static s64 get_constant_map_key(struct bpf_verifier_env *env,
/* Returns constant key value in `value` if possible, else negative error */
static int get_constant_map_key(struct bpf_verifier_env *env,
struct bpf_reg_state *key,
u32 key_size)
u32 key_size,
s64 *value)
{
struct bpf_func_state *state = func(env, key);
struct bpf_reg_state *reg;
Expand All @@ -9179,8 +9180,10 @@ static s64 get_constant_map_key(struct bpf_verifier_env *env,
/* First handle precisely tracked STACK_ZERO */
for (i = off; i >= 0 && stype[i] == STACK_ZERO; i--)
zero_size++;
if (zero_size >= key_size)
if (zero_size >= key_size) {
*value = 0;
return 0;
}

/* Check that stack contains a scalar spill of expected size */
if (!is_spilled_scalar_reg(&state->stack[spi]))
Expand All @@ -9203,9 +9206,12 @@ static s64 get_constant_map_key(struct bpf_verifier_env *env,
if (err < 0)
return err;

return reg->var_off.value;
*value = reg->var_off.value;
return 0;
}

static bool can_elide_value_nullness(enum bpf_map_type type);

static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
struct bpf_call_arg_meta *meta,
const struct bpf_func_proto *fn,
Expand Down Expand Up @@ -9354,9 +9360,16 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
err = check_helper_mem_access(env, regno, key_size, BPF_READ, false, NULL);
if (err)
return err;
meta->const_map_key = get_constant_map_key(env, reg, key_size);
if (meta->const_map_key < 0 && meta->const_map_key != -EOPNOTSUPP)
return meta->const_map_key;
if (can_elide_value_nullness(meta->map_ptr->map_type)) {
err = get_constant_map_key(env, reg, key_size, &meta->const_map_key);
if (err < 0) {
meta->const_map_key = -1;
if (err == -EOPNOTSUPP)
err = 0;
else
return err;
}
}
break;
case ARG_PTR_TO_MAP_VALUE:
if (type_may_be_null(arg_type) && register_is_null(reg))
Expand Down
15 changes: 15 additions & 0 deletions tools/testing/selftests/bpf/progs/verifier_array_access.c
Original file line number Diff line number Diff line change
Expand Up @@ -713,4 +713,19 @@ unsigned int non_stack_key_lookup(void)
return val->index;
}

SEC("socket")
__description("doesn't reject UINT64_MAX as s64 for irrelevant maps")
__success __retval(42)
unsigned int doesnt_reject_irrelevant_maps(void)
{
__u64 key = 0xFFFFFFFFFFFFFFFF;
struct test_val *val;

val = bpf_map_lookup_elem(&map_hash_48b, &key);
if (val)
return val->index;

return 42;
}

char _license[] SEC("license") = "GPL";
Loading