Commit 1a5223c1 authored by Chao Yu's avatar Chao Yu Committed by Gao Xiang
Browse files

erofs: do sanity check on m->type in z_erofs_load_compact_lcluster()



All below functions will do sanity check on m->type, let's move sanity
check to z_erofs_load_compact_lcluster() for cleanup.
- z_erofs_map_blocks_fo
- z_erofs_get_extent_compressedlen
- z_erofs_get_extent_decompressedlen
- z_erofs_extent_lookback

Reviewed-by: default avatarHongbo Li <lihongbo22@huawei.com>
Signed-off-by: default avatarChao Yu <chao@kernel.org>
Reviewed-by: default avatarGao Xiang <hsiangkao@linux.alibaba.com>
Link: https://lore.kernel.org/r/20250708110928.3110375-1-chao@kernel.org


Signed-off-by: default avatarGao Xiang <hsiangkao@linux.alibaba.com>
parent 96debe8c
Loading
Loading
Loading
Loading
+41 −62
Original line number Diff line number Diff line
@@ -240,6 +240,13 @@ static int z_erofs_load_compact_lcluster(struct z_erofs_maprecorder *m,
static int z_erofs_load_lcluster_from_disk(struct z_erofs_maprecorder *m,
					   unsigned int lcn, bool lookahead)
{
	if (m->type >= Z_EROFS_LCLUSTER_TYPE_MAX) {
		erofs_err(m->inode->i_sb, "unknown type %u @ lcn %u of nid %llu",
				m->type, lcn, EROFS_I(m->inode)->nid);
		DBG_BUGON(1);
		return -EOPNOTSUPP;
	}

	switch (EROFS_I(m->inode)->datalayout) {
	case EROFS_INODE_COMPRESSED_FULL:
		return z_erofs_load_full_lcluster(m, lcn);
@@ -265,12 +272,7 @@ static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m,
		if (err)
			return err;

		if (m->type >= Z_EROFS_LCLUSTER_TYPE_MAX) {
			erofs_err(sb, "unknown type %u @ lcn %lu of nid %llu",
				  m->type, lcn, vi->nid);
			DBG_BUGON(1);
			return -EOPNOTSUPP;
		} else if (m->type == Z_EROFS_LCLUSTER_TYPE_NONHEAD) {
		if (m->type == Z_EROFS_LCLUSTER_TYPE_NONHEAD) {
			lookback_distance = m->delta[0];
			if (!lookback_distance)
				break;
@@ -325,25 +327,18 @@ static int z_erofs_get_extent_compressedlen(struct z_erofs_maprecorder *m,
	DBG_BUGON(lcn == initial_lcn &&
		  m->type == Z_EROFS_LCLUSTER_TYPE_NONHEAD);

	if (m->type == Z_EROFS_LCLUSTER_TYPE_NONHEAD) {
		if (m->delta[0] != 1) {
	if (m->type == Z_EROFS_LCLUSTER_TYPE_NONHEAD && m->delta[0] != 1) {
		erofs_err(sb, "bogus CBLKCNT @ lcn %lu of nid %llu", lcn, vi->nid);
		DBG_BUGON(1);
		return -EFSCORRUPTED;
	}
		if (m->compressedblks)
			goto out;
	} else if (m->type < Z_EROFS_LCLUSTER_TYPE_MAX) {

	/*
		 * if the 1st NONHEAD lcluster is actually PLAIN or HEAD type
		 * rather than CBLKCNT, it's a 1 block-sized pcluster.
	 * if the 1st NONHEAD lcluster is actually PLAIN or HEAD type rather
	 * than CBLKCNT, it's a 1 block-sized pcluster.
	 */
	if (m->type != Z_EROFS_LCLUSTER_TYPE_NONHEAD || !m->compressedblks)
		m->compressedblks = 1;
		goto out;
	}
	erofs_err(sb, "cannot found CBLKCNT @ lcn %lu of nid %llu", lcn, vi->nid);
	DBG_BUGON(1);
	return -EFSCORRUPTED;
out:
	m->map->m_plen = erofs_pos(sb, m->compressedblks);
	return 0;
@@ -379,11 +374,6 @@ static int z_erofs_get_extent_decompressedlen(struct z_erofs_maprecorder *m)
			if (lcn != headlcn)
				break;	/* ends at the next HEAD lcluster */
			m->delta[1] = 1;
		} else {
			erofs_err(inode->i_sb, "unknown type %u @ lcn %llu of nid %llu",
				  m->type, lcn, vi->nid);
			DBG_BUGON(1);
			return -EOPNOTSUPP;
		}
		lcn += m->delta[1];
	}
@@ -428,11 +418,7 @@ static int z_erofs_map_blocks_fo(struct inode *inode,
	map->m_flags = EROFS_MAP_MAPPED | EROFS_MAP_ENCODED;
	end = (m.lcn + 1ULL) << lclusterbits;

	switch (m.type) {
	case Z_EROFS_LCLUSTER_TYPE_PLAIN:
	case Z_EROFS_LCLUSTER_TYPE_HEAD1:
	case Z_EROFS_LCLUSTER_TYPE_HEAD2:
		if (endoff >= m.clusterofs) {
	if (m.type != Z_EROFS_LCLUSTER_TYPE_NONHEAD && endoff >= m.clusterofs) {
		m.headtype = m.type;
		map->m_la = (m.lcn << lclusterbits) | m.clusterofs;
		/*
@@ -442,8 +428,8 @@ static int z_erofs_map_blocks_fo(struct inode *inode,
		 */
		if (ztailpacking && end > inode->i_size)
			end = inode->i_size;
			break;
		}
	} else {
		if (m.type != Z_EROFS_LCLUSTER_TYPE_NONHEAD) {
			/* m.lcn should be >= 1 if endoff < m.clusterofs */
			if (!m.lcn) {
				erofs_err(sb, "invalid logical cluster 0 at nid %llu",
@@ -454,18 +440,11 @@ static int z_erofs_map_blocks_fo(struct inode *inode,
			end = (m.lcn << lclusterbits) | m.clusterofs;
			map->m_flags |= EROFS_MAP_FULL_MAPPED;
			m.delta[0] = 1;
		fallthrough;
	case Z_EROFS_LCLUSTER_TYPE_NONHEAD:
		}
		/* get the corresponding first chunk */
		err = z_erofs_extent_lookback(&m, m.delta[0]);
		if (err)
			goto unmap_out;
		break;
	default:
		erofs_err(sb, "unknown type %u @ offset %llu of nid %llu",
			  m.type, ofs, vi->nid);
		err = -EOPNOTSUPP;
		goto unmap_out;
	}
	if (m.partialref)
		map->m_flags |= EROFS_MAP_PARTIAL_REF;