diff options
author | Jakub Kicinski <jakub.kicinski@netronome.com> | 2019-01-28 13:01:21 -0500 |
---|---|---|
committer | Daniel Borkmann <daniel@iogearbox.net> | 2019-01-28 17:59:46 -0500 |
commit | 8c79b35693380d856dcbbc21629682a90f26ca62 (patch) | |
tree | 7d5369d287051417dc10d1c79c492cc5b9728b20 | |
parent | c9e4576743eeda8d24dedc164d65b78877f9a98c (diff) |
tools: bpftool: fix crash with un-owned prog arrays
Prog arrays don't have 'owner_prog_type' and 'owner_jited'
fields in their fdinfo when they are created. Those fields
are set and reported when first program is checked for
compatibility by bpf_prog_array_compatible().
This means that bpftool cannot expect the fields to always
be there. Currently trying to show maps on a system with
an un-owned prog array leads to a crash:
$ bpftool map show
389: prog_array name tail_call_map flags 0x0
Error: key 'owner_prog_type' not found in fdinfo
Error: key 'owner_jited' not found in fdinfo
key 4B value 4B max_entries 4 memlock 4096B
Segmentation fault (core dumped)
We pass a NULL pointer to atoi().
Remove the assumption that fdinfo keys are always present.
Add missing validations and remove the p_err() calls which
may lead to broken JSON output as caller will not propagate
the failure.
Fixes: 99a44bef5870 ("tools: bpftool: add owner_prog_type and owner_jited to bpftool output")
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com>
Acked-by: Song Liu <songliubraving@fb.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
-rw-r--r-- | tools/bpf/bpftool/common.c | 6 | ||||
-rw-r--r-- | tools/bpf/bpftool/map.c | 17 |
2 files changed, 9 insertions, 14 deletions
diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c index 897483457bf0..f7261fad45c1 100644 --- a/tools/bpf/bpftool/common.c +++ b/tools/bpf/bpftool/common.c | |||
@@ -297,10 +297,8 @@ char *get_fdinfo(int fd, const char *key) | |||
297 | snprintf(path, sizeof(path), "/proc/self/fdinfo/%d", fd); | 297 | snprintf(path, sizeof(path), "/proc/self/fdinfo/%d", fd); |
298 | 298 | ||
299 | fdi = fopen(path, "r"); | 299 | fdi = fopen(path, "r"); |
300 | if (!fdi) { | 300 | if (!fdi) |
301 | p_err("can't open fdinfo: %s", strerror(errno)); | ||
302 | return NULL; | 301 | return NULL; |
303 | } | ||
304 | 302 | ||
305 | while ((n = getline(&line, &line_n, fdi)) > 0) { | 303 | while ((n = getline(&line, &line_n, fdi)) > 0) { |
306 | char *value; | 304 | char *value; |
@@ -313,7 +311,6 @@ char *get_fdinfo(int fd, const char *key) | |||
313 | 311 | ||
314 | value = strchr(line, '\t'); | 312 | value = strchr(line, '\t'); |
315 | if (!value || !value[1]) { | 313 | if (!value || !value[1]) { |
316 | p_err("malformed fdinfo!?"); | ||
317 | free(line); | 314 | free(line); |
318 | return NULL; | 315 | return NULL; |
319 | } | 316 | } |
@@ -326,7 +323,6 @@ char *get_fdinfo(int fd, const char *key) | |||
326 | return line; | 323 | return line; |
327 | } | 324 | } |
328 | 325 | ||
329 | p_err("key '%s' not found in fdinfo", key); | ||
330 | free(line); | 326 | free(line); |
331 | fclose(fdi); | 327 | fclose(fdi); |
332 | return NULL; | 328 | return NULL; |
diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c index 29a3468c6cf6..1ef1ee2280a2 100644 --- a/tools/bpf/bpftool/map.c +++ b/tools/bpf/bpftool/map.c | |||
@@ -513,10 +513,9 @@ static int show_map_close_json(int fd, struct bpf_map_info *info) | |||
513 | jsonw_uint_field(json_wtr, "owner_prog_type", | 513 | jsonw_uint_field(json_wtr, "owner_prog_type", |
514 | prog_type); | 514 | prog_type); |
515 | } | 515 | } |
516 | if (atoi(owner_jited)) | 516 | if (owner_jited) |
517 | jsonw_bool_field(json_wtr, "owner_jited", true); | 517 | jsonw_bool_field(json_wtr, "owner_jited", |
518 | else | 518 | !!atoi(owner_jited)); |
519 | jsonw_bool_field(json_wtr, "owner_jited", false); | ||
520 | 519 | ||
521 | free(owner_prog_type); | 520 | free(owner_prog_type); |
522 | free(owner_jited); | 521 | free(owner_jited); |
@@ -569,7 +568,8 @@ static int show_map_close_plain(int fd, struct bpf_map_info *info) | |||
569 | char *owner_prog_type = get_fdinfo(fd, "owner_prog_type"); | 568 | char *owner_prog_type = get_fdinfo(fd, "owner_prog_type"); |
570 | char *owner_jited = get_fdinfo(fd, "owner_jited"); | 569 | char *owner_jited = get_fdinfo(fd, "owner_jited"); |
571 | 570 | ||
572 | printf("\n\t"); | 571 | if (owner_prog_type || owner_jited) |
572 | printf("\n\t"); | ||
573 | if (owner_prog_type) { | 573 | if (owner_prog_type) { |
574 | unsigned int prog_type = atoi(owner_prog_type); | 574 | unsigned int prog_type = atoi(owner_prog_type); |
575 | 575 | ||
@@ -579,10 +579,9 @@ static int show_map_close_plain(int fd, struct bpf_map_info *info) | |||
579 | else | 579 | else |
580 | printf("owner_prog_type %d ", prog_type); | 580 | printf("owner_prog_type %d ", prog_type); |
581 | } | 581 | } |
582 | if (atoi(owner_jited)) | 582 | if (owner_jited) |
583 | printf("owner jited"); | 583 | printf("owner%s jited", |
584 | else | 584 | atoi(owner_jited) ? "" : " not"); |
585 | printf("owner not jited"); | ||
586 | 585 | ||
587 | free(owner_prog_type); | 586 | free(owner_prog_type); |
588 | free(owner_jited); | 587 | free(owner_jited); |