Skip to content

Commit 75a0a6d

Browse files
hsiangkaogregkh
authored andcommitted
erofs: handle NONHEAD !delta[1] lclusters gracefully
commit 0bc8061ffc733a0a246b8689b2d32a3e9204f43c upstream. syzbot reported a WARNING in iomap_iter_done: iomap_fiemap+0x73b/0x9b0 fs/iomap/fiemap.c:80 ioctl_fiemap fs/ioctl.c:220 [inline] Generally, NONHEAD lclusters won't have delta[1]==0, except for crafted images and filesystems created by pre-1.0 mkfs versions. Previously, it would immediately bail out if delta[1]==0, which led to inadequate decompressed lengths (thus FIEMAP is impacted). Treat it as delta[1]=1 to work around these legacy mkfs versions. `lclusterbits > 14` is illegal for compact indexes, error out too. Reported-by: [email protected] Closes: https://lore.kernel.org/r/[email protected] Tested-by: [email protected] Fixes: d95ae5e ("erofs: add support for the full decompressed length") Fixes: 001b8ccd0650 ("erofs: fix compact 4B support for 16k block size") Signed-off-by: Gao Xiang <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 6326a3d commit 75a0a6d

File tree

1 file changed

+9
-8
lines changed

1 file changed

+9
-8
lines changed

fs/erofs/zmap.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ static int compacted_load_cluster_from_disk(struct z_erofs_maprecorder *m,
256256
unsigned int amortizedshift;
257257
erofs_off_t pos;
258258

259-
if (lcn >= totalidx)
259+
if (lcn >= totalidx || vi->z_logical_clusterbits > 14)
260260
return -EINVAL;
261261

262262
m->lcn = lcn;
@@ -441,7 +441,7 @@ static int z_erofs_get_extent_decompressedlen(struct z_erofs_maprecorder *m)
441441
u64 lcn = m->lcn, headlcn = map->m_la >> lclusterbits;
442442
int err;
443443

444-
do {
444+
while (1) {
445445
/* handle the last EOF pcluster (no next HEAD lcluster) */
446446
if ((lcn << lclusterbits) >= inode->i_size) {
447447
map->m_llen = inode->i_size - map->m_la;
@@ -453,14 +453,16 @@ static int z_erofs_get_extent_decompressedlen(struct z_erofs_maprecorder *m)
453453
return err;
454454

455455
if (m->type == Z_EROFS_LCLUSTER_TYPE_NONHEAD) {
456-
DBG_BUGON(!m->delta[1] &&
457-
m->clusterofs != 1 << lclusterbits);
456+
/* work around invalid d1 generated by pre-1.0 mkfs */
457+
if (unlikely(!m->delta[1])) {
458+
m->delta[1] = 1;
459+
DBG_BUGON(1);
460+
}
458461
} else if (m->type == Z_EROFS_LCLUSTER_TYPE_PLAIN ||
459462
m->type == Z_EROFS_LCLUSTER_TYPE_HEAD1 ||
460463
m->type == Z_EROFS_LCLUSTER_TYPE_HEAD2) {
461-
/* go on until the next HEAD lcluster */
462464
if (lcn != headlcn)
463-
break;
465+
break; /* ends at the next HEAD lcluster */
464466
m->delta[1] = 1;
465467
} else {
466468
erofs_err(inode->i_sb, "unknown type %u @ lcn %llu of nid %llu",
@@ -469,8 +471,7 @@ static int z_erofs_get_extent_decompressedlen(struct z_erofs_maprecorder *m)
469471
return -EOPNOTSUPP;
470472
}
471473
lcn += m->delta[1];
472-
} while (m->delta[1]);
473-
474+
}
474475
map->m_llen = (lcn << lclusterbits) + m->clusterofs - map->m_la;
475476
return 0;
476477
}

0 commit comments

Comments
 (0)