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

perf kmaps: Check kmaps to make code more robust

This patch add checks in places where map__kmap is used to get kmaps
from struct kmap.

Error messages are added at map__kmap to warn invalid accessing of kmap
(for the case of !map->dso->kernel, kmap(map) does not exists at all).

Also, introduces map__kmaps() to warn uninitialized kmaps.

Reviewed-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: pi3orama@163.com
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Link: http://lkml.kernel.org/r/1428394966-131044-2-git-send-email-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Wang Nan and committed by
Arnaldo Carvalho de Melo
ba92732e 8ea92ceb

+70 -16
+4 -1
tools/perf/util/machine.c
··· 679 679 machine->vmlinux_maps[type]->unmap_ip = 680 680 identity__map_ip; 681 681 kmap = map__kmap(machine->vmlinux_maps[type]); 682 + if (!kmap) 683 + return -1; 684 + 682 685 kmap->kmaps = &machine->kmaps; 683 686 map_groups__insert(&machine->kmaps, 684 687 machine->vmlinux_maps[type]); ··· 703 700 kmap = map__kmap(machine->vmlinux_maps[type]); 704 701 map_groups__remove(&machine->kmaps, 705 702 machine->vmlinux_maps[type]); 706 - if (kmap->ref_reloc_sym) { 703 + if (kmap && kmap->ref_reloc_sym) { 707 704 /* 708 705 * ref_reloc_sym is shared among all maps, so free just 709 706 * on one of them.
+20
tools/perf/util/map.c
··· 778 778 return rb_entry(next, struct map, rb_node); 779 779 return NULL; 780 780 } 781 + 782 + struct kmap *map__kmap(struct map *map) 783 + { 784 + if (!map->dso || !map->dso->kernel) { 785 + pr_err("Internal error: map__kmap with a non-kernel map\n"); 786 + return NULL; 787 + } 788 + return (struct kmap *)(map + 1); 789 + } 790 + 791 + struct map_groups *map__kmaps(struct map *map) 792 + { 793 + struct kmap *kmap = map__kmap(map); 794 + 795 + if (!kmap || !kmap->kmaps) { 796 + pr_err("Internal error: map__kmaps with a non-kernel map\n"); 797 + return NULL; 798 + } 799 + return kmap->kmaps; 800 + }
+2 -4
tools/perf/util/map.h
··· 76 76 77 77 void map_groups__put(struct map_groups *mg); 78 78 79 - static inline struct kmap *map__kmap(struct map *map) 80 - { 81 - return (struct kmap *)(map + 1); 82 - } 79 + struct kmap *map__kmap(struct map *map); 80 + struct map_groups *map__kmaps(struct map *map); 83 81 84 82 static inline u64 map__map_ip(struct map *map, u64 ip) 85 83 {
+2
tools/perf/util/probe-event.c
··· 135 135 return NULL; 136 136 137 137 kmap = map__kmap(host_machine->vmlinux_maps[MAP__FUNCTION]); 138 + if (!kmap) 139 + return NULL; 138 140 return kmap->ref_reloc_sym; 139 141 } 140 142
+3
tools/perf/util/session.c
··· 1466 1466 1467 1467 for (i = 0; i < MAP__NR_TYPES; ++i) { 1468 1468 struct kmap *kmap = map__kmap(maps[i]); 1469 + 1470 + if (!kmap) 1471 + continue; 1469 1472 kmap->ref_reloc_sym = ref; 1470 1473 } 1471 1474
+11 -5
tools/perf/util/symbol-elf.c
··· 776 776 symbol_filter_t filter, int kmodule) 777 777 { 778 778 struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL; 779 + struct map_groups *kmaps = kmap ? map__kmaps(map) : NULL; 779 780 struct map *curr_map = map; 780 781 struct dso *curr_dso = dso; 781 782 Elf_Data *symstrs, *secstrs; ··· 791 790 Elf *elf; 792 791 int nr = 0; 793 792 bool remap_kernel = false, adjust_kernel_syms = false; 793 + 794 + if (kmap && !kmaps) 795 + return -1; 794 796 795 797 dso->symtab_type = syms_ss->type; 796 798 dso->is_64_bit = syms_ss->is_64_bit; ··· 962 958 map->map_ip = map__map_ip; 963 959 map->unmap_ip = map__unmap_ip; 964 960 /* Ensure maps are correctly ordered */ 965 - map_groups__remove(kmap->kmaps, map); 966 - map_groups__insert(kmap->kmaps, map); 961 + if (kmaps) { 962 + map_groups__remove(kmaps, map); 963 + map_groups__insert(kmaps, map); 964 + } 967 965 } 968 966 969 967 /* ··· 989 983 snprintf(dso_name, sizeof(dso_name), 990 984 "%s%s", dso->short_name, section_name); 991 985 992 - curr_map = map_groups__find_by_name(kmap->kmaps, map->type, dso_name); 986 + curr_map = map_groups__find_by_name(kmaps, map->type, dso_name); 993 987 if (curr_map == NULL) { 994 988 u64 start = sym.st_value; 995 989 ··· 1019 1013 curr_map->unmap_ip = identity__map_ip; 1020 1014 } 1021 1015 curr_dso->symtab_type = dso->symtab_type; 1022 - map_groups__insert(kmap->kmaps, curr_map); 1016 + map_groups__insert(kmaps, curr_map); 1023 1017 /* 1024 1018 * The new DSO should go to the kernel DSOS 1025 1019 */ ··· 1081 1075 * We need to fixup this here too because we create new 1082 1076 * maps here, for things like vsyscall sections. 1083 1077 */ 1084 - __map_groups__fixup_end(kmap->kmaps, map->type); 1078 + __map_groups__fixup_end(kmaps, map->type); 1085 1079 } 1086 1080 } 1087 1081 err = nr;
+28 -6
tools/perf/util/symbol.c
··· 630 630 static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map, 631 631 symbol_filter_t filter) 632 632 { 633 - struct map_groups *kmaps = map__kmap(map)->kmaps; 633 + struct map_groups *kmaps = map__kmaps(map); 634 634 struct map *curr_map; 635 635 struct symbol *pos; 636 636 int count = 0, moved = 0; 637 637 struct rb_root *root = &dso->symbols[map->type]; 638 638 struct rb_node *next = rb_first(root); 639 + 640 + if (!kmaps) 641 + return -1; 639 642 640 643 while (next) { 641 644 char *module; ··· 685 682 static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta, 686 683 symbol_filter_t filter) 687 684 { 688 - struct map_groups *kmaps = map__kmap(map)->kmaps; 689 - struct machine *machine = kmaps->machine; 685 + struct map_groups *kmaps = map__kmaps(map); 686 + struct machine *machine; 690 687 struct map *curr_map = map; 691 688 struct symbol *pos; 692 689 int count = 0, moved = 0; 693 690 struct rb_root *root = &dso->symbols[map->type]; 694 691 struct rb_node *next = rb_first(root); 695 692 int kernel_range = 0; 693 + 694 + if (!kmaps) 695 + return -1; 696 + 697 + machine = kmaps->machine; 696 698 697 699 while (next) { 698 700 char *module; ··· 1033 1025 static int validate_kcore_modules(const char *kallsyms_filename, 1034 1026 struct map *map) 1035 1027 { 1036 - struct map_groups *kmaps = map__kmap(map)->kmaps; 1028 + struct map_groups *kmaps = map__kmaps(map); 1037 1029 char modules_filename[PATH_MAX]; 1030 + 1031 + if (!kmaps) 1032 + return -EINVAL; 1038 1033 1039 1034 if (!filename_from_kallsyms_filename(modules_filename, "modules", 1040 1035 kallsyms_filename)) ··· 1053 1042 struct map *map) 1054 1043 { 1055 1044 struct kmap *kmap = map__kmap(map); 1045 + 1046 + if (!kmap) 1047 + return -EINVAL; 1056 1048 1057 1049 if (kmap->ref_reloc_sym && kmap->ref_reloc_sym->name) { 1058 1050 u64 start; ··· 1095 1081 static int dso__load_kcore(struct dso *dso, struct map *map, 1096 1082 const char *kallsyms_filename) 1097 1083 { 1098 - struct map_groups *kmaps = map__kmap(map)->kmaps; 1099 - struct machine *machine = kmaps->machine; 1084 + struct map_groups *kmaps = map__kmaps(map); 1085 + struct machine *machine; 1100 1086 struct kcore_mapfn_data md; 1101 1087 struct map *old_map, *new_map, *replacement_map = NULL; 1102 1088 bool is_64_bit; 1103 1089 int err, fd; 1104 1090 char kcore_filename[PATH_MAX]; 1105 1091 struct symbol *sym; 1092 + 1093 + if (!kmaps) 1094 + return -EINVAL; 1095 + 1096 + machine = kmaps->machine; 1106 1097 1107 1098 /* This function requires that the map is the kernel map */ 1108 1099 if (map != machine->vmlinux_maps[map->type]) ··· 1220 1201 { 1221 1202 struct kmap *kmap = map__kmap(map); 1222 1203 u64 addr; 1204 + 1205 + if (!kmap) 1206 + return -1; 1223 1207 1224 1208 if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->name) 1225 1209 return 0;