Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bpf: verifier: Do not extract constant map keys for irrelevant maps

Previously, we were trying to extract constant map keys for all
bpf_map_lookup_elem(), regardless of map type. This is an issue if the
map has a u64 key and the value is very high, as it can be interpreted
as a negative signed value. This in turn is treated as an error value by
check_func_arg() which causes a valid program to be incorrectly
rejected.

Fix by only extracting constant map keys for relevant maps. This fix
works because nullness elision is only allowed for {PERCPU_}ARRAY maps,
and keys for these are within u32 range. See next commit for an example
via selftest.

Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Reported-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reported-by: Ilya Leoshkevich <iii@linux.ibm.com>
Tested-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Daniel Xu <dxu@dxuuu.xyz>
Link: https://lore.kernel.org/r/aa868b642b026ff87ba6105ea151bc8693b35932.1738689872.git.dxu@dxuuu.xyz
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Daniel Xu and committed by
Alexei Starovoitov
884c3a18 517e8a78

+7 -3
+7 -3
kernel/bpf/verifier.c
··· 9206 9206 return reg->var_off.value; 9207 9207 } 9208 9208 9209 + static bool can_elide_value_nullness(enum bpf_map_type type); 9210 + 9209 9211 static int check_func_arg(struct bpf_verifier_env *env, u32 arg, 9210 9212 struct bpf_call_arg_meta *meta, 9211 9213 const struct bpf_func_proto *fn, ··· 9356 9354 err = check_helper_mem_access(env, regno, key_size, BPF_READ, false, NULL); 9357 9355 if (err) 9358 9356 return err; 9359 - meta->const_map_key = get_constant_map_key(env, reg, key_size); 9360 - if (meta->const_map_key < 0 && meta->const_map_key != -EOPNOTSUPP) 9361 - return meta->const_map_key; 9357 + if (can_elide_value_nullness(meta->map_ptr->map_type)) { 9358 + meta->const_map_key = get_constant_map_key(env, reg, key_size); 9359 + if (meta->const_map_key < 0 && meta->const_map_key != -EOPNOTSUPP) 9360 + return meta->const_map_key; 9361 + } 9362 9362 break; 9363 9363 case ARG_PTR_TO_MAP_VALUE: 9364 9364 if (type_may_be_null(arg_type) && register_is_null(reg))