Skip to content

Commit 573b3aa

Browse files
yonghong-songborkmann
authored andcommitted
tools/bpftool: fix a percpu_array map dump problem
I hit the following problem when I tried to use bpftool to dump a percpu array. $ sudo ./bpftool map show 61: percpu_array name stub flags 0x0 key 4B value 4B max_entries 1 memlock 4096B ... $ sudo ./bpftool map dump id 61 bpftool: malloc.c:2406: sysmalloc: Assertion `(old_top == initial_top (av) && old_size == 0) || \ ((unsigned long) (old_size) >= MINSIZE && \ prev_inuse (old_top) && \ ((unsigned long) old_end & (pagesize - 1)) == 0)' failed. Aborted Further debugging revealed that this is due to miscommunication between bpftool and kernel. For example, for the above percpu_array with value size of 4B. The map info returned to user space has value size of 4B. In bpftool, the values array for lookup is allocated like: info->value_size * get_possible_cpus() = 4 * get_possible_cpus() In kernel (kernel/bpf/syscall.c), the values array size is rounded up to multiple of 8. round_up(map->value_size, 8) * num_possible_cpus() = 8 * num_possible_cpus() So when kernel copies the values to user buffer, the kernel will overwrite beyond user buffer boundary. This patch fixed the issue by allocating and stepping through percpu map value array properly in bpftool. Fixes: 71bb428 ("tools: bpf: add bpftool") Signed-off-by: Yonghong Song <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]>
1 parent 61f4b23 commit 573b3aa

File tree

1 file changed

+9
-5
lines changed

1 file changed

+9
-5
lines changed

tools/bpf/bpftool/map.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include <assert.h>
3737
#include <errno.h>
3838
#include <fcntl.h>
39+
#include <linux/kernel.h>
3940
#include <stdbool.h>
4041
#include <stdio.h>
4142
#include <stdlib.h>
@@ -90,7 +91,8 @@ static bool map_is_map_of_progs(__u32 type)
9091
static void *alloc_value(struct bpf_map_info *info)
9192
{
9293
if (map_is_per_cpu(info->type))
93-
return malloc(info->value_size * get_possible_cpus());
94+
return malloc(round_up(info->value_size, 8) *
95+
get_possible_cpus());
9496
else
9597
return malloc(info->value_size);
9698
}
@@ -161,9 +163,10 @@ static void print_entry_json(struct bpf_map_info *info, unsigned char *key,
161163
jsonw_name(json_wtr, "value");
162164
print_hex_data_json(value, info->value_size);
163165
} else {
164-
unsigned int i, n;
166+
unsigned int i, n, step;
165167

166168
n = get_possible_cpus();
169+
step = round_up(info->value_size, 8);
167170

168171
jsonw_name(json_wtr, "key");
169172
print_hex_data_json(key, info->key_size);
@@ -176,7 +179,7 @@ static void print_entry_json(struct bpf_map_info *info, unsigned char *key,
176179
jsonw_int_field(json_wtr, "cpu", i);
177180

178181
jsonw_name(json_wtr, "value");
179-
print_hex_data_json(value + i * info->value_size,
182+
print_hex_data_json(value + i * step,
180183
info->value_size);
181184

182185
jsonw_end_object(json_wtr);
@@ -207,17 +210,18 @@ static void print_entry_plain(struct bpf_map_info *info, unsigned char *key,
207210

208211
printf("\n");
209212
} else {
210-
unsigned int i, n;
213+
unsigned int i, n, step;
211214

212215
n = get_possible_cpus();
216+
step = round_up(info->value_size, 8);
213217

214218
printf("key:\n");
215219
fprint_hex(stdout, key, info->key_size, " ");
216220
printf("\n");
217221
for (i = 0; i < n; i++) {
218222
printf("value (CPU %02d):%c",
219223
i, info->value_size > 16 ? '\n' : ' ');
220-
fprint_hex(stdout, value + i * info->value_size,
224+
fprint_hex(stdout, value + i * step,
221225
info->value_size, " ");
222226
printf("\n");
223227
}

0 commit comments

Comments
 (0)