@@ -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,
240236static 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
260264static 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