Unverified Commit 674ed576 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!11391 fix CVE-2023-45896

Merge Pull Request from: @ci-robot 
 
PR sync from: Lin Yujun <linyujun809@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/AWMC3YGFJOG6DARWA76ZHIR6XWUNXB77/ 
Konstantin Komarov (1):
  fs/ntfs3: Add more attributes checks in mi_enum_attr()


-- 
2.34.1
 
https://gitee.com/src-openeuler/kernel/issues/IAN1IM 
 
Link:https://gitee.com/openeuler/kernel/pulls/11391

 

Reviewed-by: default avatarZhang Jianhua <chris.zjh@huawei.com>
Signed-off-by: default avatarYang Yingliang <yangyingliang@huawei.com>
parents d4102e90 df1851ab
Loading
Loading
Loading
Loading
+50 −13
Original line number Diff line number Diff line
@@ -187,8 +187,9 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)
{
	const struct MFT_REC *rec = mi->mrec;
	u32 used = le32_to_cpu(rec->used);
	u32 t32, off, asize;
	u32 t32, off, asize, prev_type;
	u16 t16;
	u64 data_size, alloc_size, tot_size;

	if (!attr) {
		u32 total = le32_to_cpu(rec->total);
@@ -207,6 +208,7 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)
		if (!is_rec_inuse(rec))
			return NULL;

		prev_type = 0;
		attr = Add2Ptr(rec, off);
	} else {
		/* Check if input attr inside record. */
@@ -220,6 +222,7 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)
			return NULL;
		}

		prev_type = le32_to_cpu(attr->type);
		attr = Add2Ptr(attr, asize);
		off += asize;
	}
@@ -239,7 +242,11 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)

	/* 0x100 is last known attribute for now. */
	t32 = le32_to_cpu(attr->type);
	if ((t32 & 0xf) || (t32 > 0x100))
	if (!t32 || (t32 & 0xf) || (t32 > 0x100))
		return NULL;

	/* attributes in record must be ordered by type */
	if (t32 < prev_type)
		return NULL;

	/* Check boundary. */
@@ -248,16 +255,15 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)

	/* Check size of attribute. */
	if (!attr->non_res) {
		/* Check resident fields. */
		if (asize < SIZEOF_RESIDENT)
			return NULL;

		t16 = le16_to_cpu(attr->res.data_off);

		if (t16 > asize)
			return NULL;

		t32 = le32_to_cpu(attr->res.data_size);
		if (t32 > asize - t16)
		if (t16 + le32_to_cpu(attr->res.data_size) > asize)
			return NULL;

		if (attr->name_len &&
@@ -268,21 +274,52 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)
		return attr;
	}

	/* Check some nonresident fields. */
	if (attr->name_len &&
	    le16_to_cpu(attr->name_off) + sizeof(short) * attr->name_len >
		    le16_to_cpu(attr->nres.run_off)) {
	/* Check nonresident fields. */
	if (attr->non_res != 1)
		return NULL;

	t16 = le16_to_cpu(attr->nres.run_off);
	if (t16 > asize)
		return NULL;

	t32 = sizeof(short) * attr->name_len;
	if (t32 && le16_to_cpu(attr->name_off) + t32 > t16)
		return NULL;

	/* Check start/end vcn. */
	if (le64_to_cpu(attr->nres.svcn) > le64_to_cpu(attr->nres.evcn) + 1)
		return NULL;

	data_size = le64_to_cpu(attr->nres.data_size);
	if (le64_to_cpu(attr->nres.valid_size) > data_size)
		return NULL;

	alloc_size = le64_to_cpu(attr->nres.alloc_size);
	if (data_size > alloc_size)
		return NULL;

	t32 = mi->sbi->cluster_mask;
	if (alloc_size & t32)
		return NULL;

	if (!attr->nres.svcn && is_attr_ext(attr)) {
		/* First segment of sparse/compressed attribute */
		if (asize + 8 < SIZEOF_NONRESIDENT_EX)
			return NULL;
	}

	if (attr->nres.svcn || !is_attr_ext(attr)) {
		tot_size = le64_to_cpu(attr->nres.total_size);
		if (tot_size & t32)
			return NULL;

		if (tot_size > alloc_size)
			return NULL;
	} else {
		if (asize + 8 < SIZEOF_NONRESIDENT)
			return NULL;

		if (attr->nres.c_unit)
			return NULL;
	} else if (asize + 8 < SIZEOF_NONRESIDENT_EX)
		return NULL;
	}

	return attr;
}