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

bpf: Fix elem_size not being set for inner maps

Commit d937bc3449fa ("bpf: make uniform use of array->elem_size
everywhere in arraymap.c") changed array_map_gen_lookup to use
array->elem_size instead of round_up(map->value_size, 8) as the element
size when generating code to access a value in an array map.

array->elem_size, however, is not set by bpf_map_meta_alloc when
initializing an BPF_MAP_TYPE_ARRAY_OF_MAPS or BPF_MAP_TYPE_HASH_OF_MAPS.
This results in array_map_gen_lookup incorrectly outputting code that
always accesses index 0 in the array (as the index will be calculated
via a multiplication with the element size, which is incorrectly set to
0).

Set elem_size on the bpf_array object when allocating an array or hash
of maps to fix this.

Fixes: d937bc3449fa ("bpf: make uniform use of array->elem_size everywhere in arraymap.c")
Signed-off-by: Rhys Rustad-Elliott <me@rhysre.net>
Link: https://lore.kernel.org/r/20230602190110.47068-2-me@rhysre.net
Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>

authored by

Rhys Rustad-Elliott and committed by
Martin KaFai Lau
cba41bb7 b0fd1852

+6 -2
+6 -2
kernel/bpf/map_in_map.c
··· 69 69 /* Misc members not needed in bpf_map_meta_equal() check. */ 70 70 inner_map_meta->ops = inner_map->ops; 71 71 if (inner_map->ops == &array_map_ops) { 72 + struct bpf_array *inner_array_meta = 73 + container_of(inner_map_meta, struct bpf_array, map); 74 + struct bpf_array *inner_array = container_of(inner_map, struct bpf_array, map); 75 + 76 + inner_array_meta->index_mask = inner_array->index_mask; 77 + inner_array_meta->elem_size = inner_array->elem_size; 72 78 inner_map_meta->bypass_spec_v1 = inner_map->bypass_spec_v1; 73 - container_of(inner_map_meta, struct bpf_array, map)->index_mask = 74 - container_of(inner_map, struct bpf_array, map)->index_mask; 75 79 } 76 80 77 81 fdput(f);