Skip to content

Commit 250a17e

Browse files
committed
Merge tag 'erofs-for-6.18-rc3-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs
Pull erofs fixes from Gao Xiang: "Just three small fixes to address fuzzed images in relatively new features, as reported by Robert. - Hardening against fuzzed encoded extents - Fix infinite loops due to crafted subpage compact indexes - Improve z_erofs_extent_lookback()" * tag 'erofs-for-6.18-rc3-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs: erofs: consolidate z_erofs_extent_lookback() erofs: avoid infinite loops due to corrupted subpage compact indexes erofs: fix crafted invalid cases for encoded extents
2 parents 9ea7460 + 2a13fc4 commit 250a17e

1 file changed

Lines changed: 30 additions & 29 deletions

File tree

fs/erofs/zmap.c

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,6 @@ static int z_erofs_load_full_lcluster(struct z_erofs_maprecorder *m,
5555
} else {
5656
m->partialref = !!(advise & Z_EROFS_LI_PARTIAL_REF);
5757
m->clusterofs = le16_to_cpu(di->di_clusterofs);
58-
if (m->clusterofs >= 1 << vi->z_lclusterbits) {
59-
DBG_BUGON(1);
60-
return -EFSCORRUPTED;
61-
}
6258
m->pblk = le32_to_cpu(di->di_u.blkaddr);
6359
}
6460
return 0;
@@ -240,21 +236,29 @@ static int z_erofs_load_compact_lcluster(struct z_erofs_maprecorder *m,
240236
static int z_erofs_load_lcluster_from_disk(struct z_erofs_maprecorder *m,
241237
unsigned int lcn, bool lookahead)
242238
{
239+
struct erofs_inode *vi = EROFS_I(m->inode);
240+
int err;
241+
242+
if (vi->datalayout == EROFS_INODE_COMPRESSED_COMPACT) {
243+
err = z_erofs_load_compact_lcluster(m, lcn, lookahead);
244+
} else {
245+
DBG_BUGON(vi->datalayout != EROFS_INODE_COMPRESSED_FULL);
246+
err = z_erofs_load_full_lcluster(m, lcn);
247+
}
248+
if (err)
249+
return err;
250+
243251
if (m->type >= Z_EROFS_LCLUSTER_TYPE_MAX) {
244252
erofs_err(m->inode->i_sb, "unknown type %u @ lcn %u of nid %llu",
245-
m->type, lcn, EROFS_I(m->inode)->nid);
253+
m->type, lcn, EROFS_I(m->inode)->nid);
246254
DBG_BUGON(1);
247255
return -EOPNOTSUPP;
256+
} else if (m->type != Z_EROFS_LCLUSTER_TYPE_NONHEAD &&
257+
m->clusterofs >= (1 << vi->z_lclusterbits)) {
258+
DBG_BUGON(1);
259+
return -EFSCORRUPTED;
248260
}
249-
250-
switch (EROFS_I(m->inode)->datalayout) {
251-
case EROFS_INODE_COMPRESSED_FULL:
252-
return z_erofs_load_full_lcluster(m, lcn);
253-
case EROFS_INODE_COMPRESSED_COMPACT:
254-
return z_erofs_load_compact_lcluster(m, lcn, lookahead);
255-
default:
256-
return -EINVAL;
257-
}
261+
return 0;
258262
}
259263

260264
static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m,
@@ -268,20 +272,19 @@ static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m,
268272
unsigned long lcn = m->lcn - lookback_distance;
269273
int err;
270274

275+
if (!lookback_distance)
276+
break;
277+
271278
err = z_erofs_load_lcluster_from_disk(m, lcn, false);
272279
if (err)
273280
return err;
274-
275281
if (m->type == Z_EROFS_LCLUSTER_TYPE_NONHEAD) {
276282
lookback_distance = m->delta[0];
277-
if (!lookback_distance)
278-
break;
279283
continue;
280-
} else {
281-
m->headtype = m->type;
282-
m->map->m_la = (lcn << lclusterbits) | m->clusterofs;
283-
return 0;
284284
}
285+
m->headtype = m->type;
286+
m->map->m_la = (lcn << lclusterbits) | m->clusterofs;
287+
return 0;
285288
}
286289
erofs_err(sb, "bogus lookback distance %u @ lcn %lu of nid %llu",
287290
lookback_distance, m->lcn, vi->nid);
@@ -431,13 +434,6 @@ static int z_erofs_map_blocks_fo(struct inode *inode,
431434
end = inode->i_size;
432435
} else {
433436
if (m.type != Z_EROFS_LCLUSTER_TYPE_NONHEAD) {
434-
/* m.lcn should be >= 1 if endoff < m.clusterofs */
435-
if (!m.lcn) {
436-
erofs_err(sb, "invalid logical cluster 0 at nid %llu",
437-
vi->nid);
438-
err = -EFSCORRUPTED;
439-
goto unmap_out;
440-
}
441437
end = (m.lcn << lclusterbits) | m.clusterofs;
442438
map->m_flags |= EROFS_MAP_FULL_MAPPED;
443439
m.delta[0] = 1;
@@ -596,7 +592,7 @@ static int z_erofs_map_blocks_ext(struct inode *inode,
596592
vi->z_fragmentoff = map->m_plen;
597593
if (recsz > offsetof(struct z_erofs_extent, pstart_lo))
598594
vi->z_fragmentoff |= map->m_pa << 32;
599-
} else if (map->m_plen) {
595+
} else if (map->m_plen & Z_EROFS_EXTENT_PLEN_MASK) {
600596
map->m_flags |= EROFS_MAP_MAPPED |
601597
EROFS_MAP_FULL_MAPPED | EROFS_MAP_ENCODED;
602598
fmt = map->m_plen >> Z_EROFS_EXTENT_PLEN_FMT_BIT;
@@ -715,6 +711,7 @@ static int z_erofs_map_sanity_check(struct inode *inode,
715711
struct erofs_map_blocks *map)
716712
{
717713
struct erofs_sb_info *sbi = EROFS_I_SB(inode);
714+
u64 pend;
718715

719716
if (!(map->m_flags & EROFS_MAP_ENCODED))
720717
return 0;
@@ -732,6 +729,10 @@ static int z_erofs_map_sanity_check(struct inode *inode,
732729
if (unlikely(map->m_plen > Z_EROFS_PCLUSTER_MAX_SIZE ||
733730
map->m_llen > Z_EROFS_PCLUSTER_MAX_DSIZE))
734731
return -EOPNOTSUPP;
732+
/* Filesystems beyond 48-bit physical block addresses are invalid */
733+
if (unlikely(check_add_overflow(map->m_pa, map->m_plen, &pend) ||
734+
(pend >> sbi->blkszbits) >= BIT_ULL(48)))
735+
return -EFSCORRUPTED;
735736
return 0;
736737
}
737738

0 commit comments

Comments
 (0)