gossipd: remove gossmap_fetch_tail.
What changed, and why it matters
This commit removes a rarely-used diagnostic helper called gossmap_fetch_tail that could crash the gossip daemon when it tried to read the tail of a corrupted or truncated gossip map. The crash happened during an internal error path (the daemon was already about to exit), so it is more of a crash-on-failure than an exploitable vulnerability. The fix simply stops calling the helper and reports the remaining file data from the regular file descriptor instead.
Apply the patch to remove gossmap_fetch_tail and rely on fetch_tail_fd for diagnostics. No immediate mitigation required beyond normal update; the crash is only reachable during an already-failing internal state. Monitor gossip_store integrity and logs for 'Truncated gossmap record' warnings.
Security signals we found
Crash/assertion failure in error-handling path
Removal of unsafe diagnostic helper using mmap after mmap is disabled on error
Backtrace shows SIGABRT from __assert_fail inside map_copy called by gossmap_fetch_tail
Evidence from the diff
gossmap_fetch_tail() in common/gossmap.c copied the unprocessed tail of the gossip map using map_copy(), which contained an assertion that could fail when the map was in an inconsistent state (e.g., mmap disabled after an error, or truncated record). The function was only invoked from a status_failed() diagnostic path in gossipd/gossmap_manage.c when the gossip store was not fully processed. The patch deletes gossmap_fetch_tail() and its header declaration, and changes the diagnostic logging to only show the remainder fetched via the file descriptor (fetch_tail_fd). This prevents an assertion crash/SIGABRT while the daemon is already shutting down due to an internal error.
Changed components
common/gossmap.ccommon/gossmap.hgossipd/gossmap_manage.cgossipd daemonInspect captured patch +2 / −24
diff --git a/common/gossmap.c b/common/gossmap.c
index 685bdd4a..c0ea7e6c 100644
--- a/common/gossmap.c
+++ b/common/gossmap.c
@@ -1868,17 +1868,3 @@ void gossmap_disable_mmap(struct gossmap *map)
munmap(map->mmap, map->map_size);
map->mmap = NULL;
}
-
-const u8 *gossmap_fetch_tail(const tal_t *ctx, const struct gossmap *map)
-{
- size_t len;
- u8 *p;
-
- /* Shouldn't happen... */
- if (map->map_end > map->map_size)
- return NULL;
- len = map->map_size - map->map_end;
- p = tal_arr(ctx, u8, len);
- map_copy(map, map->map_size, p, len);
- return p;
-}
diff --git a/common/gossmap.h b/common/gossmap.h
index a7c00586..ef3b71a6 100644
--- a/common/gossmap.h
+++ b/common/gossmap.h
@@ -308,7 +308,4 @@ u64 gossmap_lengths(const struct gossmap *map, u64 *total);
/* Debugging: connectd wants to enumerate fds */
int gossmap_fd(const struct gossmap *map);
-
-/* Fetch unprocessed part of gossmap */
-const u8 *gossmap_fetch_tail(const tal_t *ctx, const struct gossmap *map);
#endif /* LIGHTNING_COMMON_GOSSMAP_H */
diff --git a/gossipd/gossmap_manage.c b/gossipd/gossmap_manage.c
index 29b0a8db..ed24fe9a 100644
--- a/gossipd/gossmap_manage.c
+++ b/gossipd/gossmap_manage.c
@@ -1434,20 +1434,15 @@ struct gossmap *gossmap_manage_get_gossmap(struct gossmap_manage *gm)
" used=%"PRIu64" seen=%"PRIu64" written=%"PRIu64,
map_used, map_size, written_len);
} else if (map_size != map_used) {
- const u8 *remainder_fd, *remainder_mmap;
+ const u8 *remainder_fd;
- /* Sigh. Did gossmap see something different (via mmap)
- * from what we see via read? It's possible it's caught up
- * now, but just in case, log BOTH */
- remainder_mmap = gossmap_fetch_tail(tmpctx, gm->raw_gossmap);
remainder_fd = fetch_tail_fd(tmpctx,
gossmap_fd(gm->raw_gossmap),
map_used, map_size);
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Gossmap failed to process entire gossip_store: "
- "at %"PRIu64" of %"PRIu64" remaining_mmap=%s remaining_fd=%s",
+ "at %"PRIu64" of %"PRIu64" remaining_fd=%s",
map_used, map_size,
- tal_hex(tmpctx, remainder_mmap),
tal_hex(tmpctx, remainder_fd));
}
Why this scored 42/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.