Skip to content

Commit 79c9995

Browse files
committed
Fix ZFS panic on space map corruption
Add defensive validation to prevent kernel panics when corrupted space map data is encountered during pool import. Instead of panicking, the system now logs corruption and continues in read-only mode. Changes: - space_map.c: Add bounds checking in space_map_load_callback to skip zero-sized and out-of-bounds entries - range_tree.c: Add defensive check in zfs_range_tree_remove_impl to detect corrupted segment bounds and recover gracefully
1 parent fc519b2 commit 79c9995

File tree

2 files changed

+27
-0
lines changed

2 files changed

+27
-0
lines changed

module/zfs/range_tree.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,18 @@ zfs_range_tree_remove_impl(zfs_range_tree_t *rt, uint64_t start, uint64_t size,
503503
rstart = zfs_rs_get_start(rs, rt);
504504
rend = zfs_rs_get_end(rs, rt);
505505

506+
/*
507+
* Defensive check: if we detect corrupted bounds, log the issue
508+
* and try to recover rather than panicking
509+
*/
510+
if (rstart > start) {
511+
zfs_panic_recover("zfs: rt=%s: segment bounds invalid - "
512+
"existing start (%llx) > requested start (%llx), "
513+
"this may indicate corrupted space map data",
514+
ZFS_RT_NAME(rt), (longlong_t)rstart, (longlong_t)start);
515+
return;
516+
}
517+
506518
/*
507519
* Range trees with gap support must only remove complete segments
508520
* from the tree. This allows us to maintain accurate fill accounting

module/zfs/space_map.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,21 @@ static int
402402
space_map_load_callback(space_map_entry_t *sme, void *arg)
403403
{
404404
space_map_load_arg_t *smla = arg;
405+
406+
/* Validate space map entry bounds */
407+
if (sme->sme_run == 0) {
408+
return (0);
409+
}
410+
411+
if (sme->sme_offset + sme->sme_run > smla->smla_sm->sm_size) {
412+
zfs_panic_recover("Skipping out-of-bounds space map entry "
413+
"(offset=%llu, size=%llu, sm_size=%llu)",
414+
(unsigned long long)sme->sme_offset,
415+
(unsigned long long)sme->sme_run,
416+
(unsigned long long)smla->smla_sm->sm_size);
417+
return (0);
418+
}
419+
405420
if (sme->sme_type == smla->smla_type) {
406421
VERIFY3U(zfs_range_tree_space(smla->smla_rt) + sme->sme_run, <=,
407422
smla->smla_sm->sm_size);

0 commit comments

Comments
 (0)