tools/perf/util/maps.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
__maps__fixup_overlap_and_insert may split or directly insert a map,
when doing this the map may need to have a kmap set up for the sake of
the kmaps. The missing kmap set up fails the check_invariants test in
maps, later "Internal error" reports from map__kmap and ultimately
causes segfaults.
Similar fixes were added in commit e0e4e0b8b7fa ("perf maps: Add
missing map__set_kmap_maps() when replacing a kernel map") and commit
25d9c0301d36 ("perf maps: Set the kmaps for newly created/added kernel
maps") but they missed cases. To try to reduce the risk of this,
update the kmap directly following any manual insert. This identified
another problem in maps__copy_from.
Fixes: e0e4e0b8b7fa ("perf maps: Add missing map__set_kmap_maps() when replacing a kernel map")
Fixes: 25d9c0301d36 ("perf maps: Set the kmaps for newly created/added kernel maps")
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/util/maps.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/tools/perf/util/maps.c b/tools/perf/util/maps.c
index 85b2a93a59ac..779f6230130a 100644
--- a/tools/perf/util/maps.c
+++ b/tools/perf/util/maps.c
@@ -477,6 +477,7 @@ static int __maps__insert(struct maps *maps, struct map *new)
}
/* Insert the value at the end. */
maps_by_address[nr_maps] = map__get(new);
+ map__set_kmap_maps(new, maps);
if (maps_by_name)
maps_by_name[nr_maps] = map__get(new);
@@ -502,8 +503,6 @@ static int __maps__insert(struct maps *maps, struct map *new)
if (map__end(new) < map__start(new))
RC_CHK_ACCESS(maps)->ends_broken = true;
- map__set_kmap_maps(new, maps);
-
return 0;
}
@@ -891,6 +890,7 @@ static int __maps__fixup_overlap_and_insert(struct maps *maps, struct map *new)
if (before) {
map__put(maps_by_address[i]);
maps_by_address[i] = before;
+ map__set_kmap_maps(before, maps);
if (maps_by_name) {
map__put(maps_by_name[ni]);
@@ -918,6 +918,7 @@ static int __maps__fixup_overlap_and_insert(struct maps *maps, struct map *new)
*/
map__put(maps_by_address[i]);
maps_by_address[i] = map__get(new);
+ map__set_kmap_maps(new, maps);
if (maps_by_name) {
map__put(maps_by_name[ni]);
@@ -942,14 +943,13 @@ static int __maps__fixup_overlap_and_insert(struct maps *maps, struct map *new)
*/
map__put(maps_by_address[i]);
maps_by_address[i] = map__get(new);
+ map__set_kmap_maps(new, maps);
if (maps_by_name) {
map__put(maps_by_name[ni]);
maps_by_name[ni] = map__get(new);
}
- map__set_kmap_maps(new, maps);
-
check_invariants(maps);
return err;
}
@@ -1019,6 +1019,7 @@ int maps__copy_from(struct maps *dest, struct maps *parent)
err = unwind__prepare_access(dest, new, NULL);
if (!err) {
dest_maps_by_address[i] = new;
+ map__set_kmap_maps(new, dest);
if (dest_maps_by_name)
dest_maps_by_name[i] = map__get(new);
RC_CHK_ACCESS(dest)->nr_maps = i + 1;
--
2.51.0.384.g4c02a37b29-goog
On Sun, Sep 14, 2025 at 11:18 AM Ian Rogers <irogers@google.com> wrote: > > __maps__fixup_overlap_and_insert may split or directly insert a map, > when doing this the map may need to have a kmap set up for the sake of > the kmaps. The missing kmap set up fails the check_invariants test in > maps, later "Internal error" reports from map__kmap and ultimately > causes segfaults. > > Similar fixes were added in commit e0e4e0b8b7fa ("perf maps: Add > missing map__set_kmap_maps() when replacing a kernel map") and commit > 25d9c0301d36 ("perf maps: Set the kmaps for newly created/added kernel > maps") but they missed cases. To try to reduce the risk of this, > update the kmap directly following any manual insert. This identified > another problem in maps__copy_from. > > Fixes: e0e4e0b8b7fa ("perf maps: Add missing map__set_kmap_maps() when replacing a kernel map") > Fixes: 25d9c0301d36 ("perf maps: Set the kmaps for newly created/added kernel maps") > Signed-off-by: Ian Rogers <irogers@google.com> This may be worth picking up for v6.17. It was a fairly regular source of crashes on basic commands like `perf record` for me on certain kernels. `perf record` by default is processing the whole perf.data file and if there were overlapping maps, from BPF symbol events typically, the broken kmap would trigger assertion failures and seg faults. Thanks, Ian > --- > tools/perf/util/maps.c | 9 +++++---- > 1 file changed, 5 insertions(+), 4 deletions(-) > > diff --git a/tools/perf/util/maps.c b/tools/perf/util/maps.c > index 85b2a93a59ac..779f6230130a 100644 > --- a/tools/perf/util/maps.c > +++ b/tools/perf/util/maps.c > @@ -477,6 +477,7 @@ static int __maps__insert(struct maps *maps, struct map *new) > } > /* Insert the value at the end. */ > maps_by_address[nr_maps] = map__get(new); > + map__set_kmap_maps(new, maps); > if (maps_by_name) > maps_by_name[nr_maps] = map__get(new); > > @@ -502,8 +503,6 @@ static int __maps__insert(struct maps *maps, struct map *new) > if (map__end(new) < map__start(new)) > RC_CHK_ACCESS(maps)->ends_broken = true; > > - map__set_kmap_maps(new, maps); > - > return 0; > } > > @@ -891,6 +890,7 @@ static int __maps__fixup_overlap_and_insert(struct maps *maps, struct map *new) > if (before) { > map__put(maps_by_address[i]); > maps_by_address[i] = before; > + map__set_kmap_maps(before, maps); > > if (maps_by_name) { > map__put(maps_by_name[ni]); > @@ -918,6 +918,7 @@ static int __maps__fixup_overlap_and_insert(struct maps *maps, struct map *new) > */ > map__put(maps_by_address[i]); > maps_by_address[i] = map__get(new); > + map__set_kmap_maps(new, maps); > > if (maps_by_name) { > map__put(maps_by_name[ni]); > @@ -942,14 +943,13 @@ static int __maps__fixup_overlap_and_insert(struct maps *maps, struct map *new) > */ > map__put(maps_by_address[i]); > maps_by_address[i] = map__get(new); > + map__set_kmap_maps(new, maps); > > if (maps_by_name) { > map__put(maps_by_name[ni]); > maps_by_name[ni] = map__get(new); > } > > - map__set_kmap_maps(new, maps); > - > check_invariants(maps); > return err; > } > @@ -1019,6 +1019,7 @@ int maps__copy_from(struct maps *dest, struct maps *parent) > err = unwind__prepare_access(dest, new, NULL); > if (!err) { > dest_maps_by_address[i] = new; > + map__set_kmap_maps(new, dest); > if (dest_maps_by_name) > dest_maps_by_name[i] = map__get(new); > RC_CHK_ACCESS(dest)->nr_maps = i + 1; > -- > 2.51.0.384.g4c02a37b29-goog >
Hi Ian, On Mon, Sep 15, 2025 at 08:00:53AM -0700, Ian Rogers wrote: > On Sun, Sep 14, 2025 at 11:18 AM Ian Rogers <irogers@google.com> wrote: > > > > __maps__fixup_overlap_and_insert may split or directly insert a map, > > when doing this the map may need to have a kmap set up for the sake of > > the kmaps. The missing kmap set up fails the check_invariants test in > > maps, later "Internal error" reports from map__kmap and ultimately > > causes segfaults. > > > > Similar fixes were added in commit e0e4e0b8b7fa ("perf maps: Add > > missing map__set_kmap_maps() when replacing a kernel map") and commit > > 25d9c0301d36 ("perf maps: Set the kmaps for newly created/added kernel > > maps") but they missed cases. To try to reduce the risk of this, > > update the kmap directly following any manual insert. This identified > > another problem in maps__copy_from. > > > > Fixes: e0e4e0b8b7fa ("perf maps: Add missing map__set_kmap_maps() when replacing a kernel map") > > Fixes: 25d9c0301d36 ("perf maps: Set the kmaps for newly created/added kernel maps") > > Signed-off-by: Ian Rogers <irogers@google.com> > > This may be worth picking up for v6.17. It was a fairly regular source > of crashes on basic commands like `perf record` for me on certain > kernels. `perf record` by default is processing the whole perf.data > file and if there were overlapping maps, from BPF symbol events > typically, the broken kmap would trigger assertion failures and seg > faults. Sounds good, will queue it to perf-tools. Thanks, Namhyung > > --- > > tools/perf/util/maps.c | 9 +++++---- > > 1 file changed, 5 insertions(+), 4 deletions(-) > > > > diff --git a/tools/perf/util/maps.c b/tools/perf/util/maps.c > > index 85b2a93a59ac..779f6230130a 100644 > > --- a/tools/perf/util/maps.c > > +++ b/tools/perf/util/maps.c > > @@ -477,6 +477,7 @@ static int __maps__insert(struct maps *maps, struct map *new) > > } > > /* Insert the value at the end. */ > > maps_by_address[nr_maps] = map__get(new); > > + map__set_kmap_maps(new, maps); > > if (maps_by_name) > > maps_by_name[nr_maps] = map__get(new); > > > > @@ -502,8 +503,6 @@ static int __maps__insert(struct maps *maps, struct map *new) > > if (map__end(new) < map__start(new)) > > RC_CHK_ACCESS(maps)->ends_broken = true; > > > > - map__set_kmap_maps(new, maps); > > - > > return 0; > > } > > > > @@ -891,6 +890,7 @@ static int __maps__fixup_overlap_and_insert(struct maps *maps, struct map *new) > > if (before) { > > map__put(maps_by_address[i]); > > maps_by_address[i] = before; > > + map__set_kmap_maps(before, maps); > > > > if (maps_by_name) { > > map__put(maps_by_name[ni]); > > @@ -918,6 +918,7 @@ static int __maps__fixup_overlap_and_insert(struct maps *maps, struct map *new) > > */ > > map__put(maps_by_address[i]); > > maps_by_address[i] = map__get(new); > > + map__set_kmap_maps(new, maps); > > > > if (maps_by_name) { > > map__put(maps_by_name[ni]); > > @@ -942,14 +943,13 @@ static int __maps__fixup_overlap_and_insert(struct maps *maps, struct map *new) > > */ > > map__put(maps_by_address[i]); > > maps_by_address[i] = map__get(new); > > + map__set_kmap_maps(new, maps); > > > > if (maps_by_name) { > > map__put(maps_by_name[ni]); > > maps_by_name[ni] = map__get(new); > > } > > > > - map__set_kmap_maps(new, maps); > > - > > check_invariants(maps); > > return err; > > } > > @@ -1019,6 +1019,7 @@ int maps__copy_from(struct maps *dest, struct maps *parent) > > err = unwind__prepare_access(dest, new, NULL); > > if (!err) { > > dest_maps_by_address[i] = new; > > + map__set_kmap_maps(new, dest); > > if (dest_maps_by_name) > > dest_maps_by_name[i] = map__get(new); > > RC_CHK_ACCESS(dest)->nr_maps = i + 1; > > -- > > 2.51.0.384.g4c02a37b29-goog > >
© 2016 - 2025 Red Hat, Inc.