Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 61d57f5b authored by Mohammed Javid's avatar Mohammed Javid
Browse files

msm: ipa: Fix to slab out of bounds issue



Add changes to verify passed value with in the allocated
max array size range or not before accessing structure.

Change-Id: If70493e937f6f0bc29bbfe08bf43738bdb4e9cf4
Acked-by: default avatarAshok Vuyyuru <avuyyuru@qti.qualcomm.com>
Signed-off-by: default avatarMohammed Javid <mjavid@codeaurora.org>
parent aa89b686
Loading
Loading
Loading
Loading
+50 −8
Original line number Diff line number Diff line
@@ -432,6 +432,8 @@ static ssize_t ipa_read_hdr(struct file *file, char __user *ubuf, size_t count,

	list_for_each_entry(entry, &ipa_ctx->hdr_tbl.head_hdr_entry_list,
			link) {
		if (entry->cookie != IPA_HDR_COOKIE)
			continue;
		nbytes = scnprintf(
			dbg_buff,
			IPA_MAX_MSG_LEN - 1,
@@ -606,6 +608,14 @@ static int ipa_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib)
	if (attrib->protocol_eq_present)
		pr_err("protocol:%d ", attrib->protocol_eq);

	if (attrib->num_ihl_offset_range_16 >
			IPA_IPFLTR_NUM_IHL_RANGE_16_EQNS) {
		IPAERR_RL("num_ihl_offset_range_16  Max %d passed value %d\n",
			IPA_IPFLTR_NUM_IHL_RANGE_16_EQNS,
			attrib->num_ihl_offset_range_16);
		return -EPERM;
	}

	for (i = 0; i < attrib->num_ihl_offset_range_16; i++) {
		pr_err(
			   "(ihl_ofst_range16: ofst:%u lo:%u hi:%u) ",
@@ -614,6 +624,12 @@ static int ipa_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib)
			   attrib->ihl_offset_range_16[i].range_high);
	}

	if (attrib->num_offset_meq_32 > IPA_IPFLTR_NUM_MEQ_32_EQNS) {
		IPAERR_RL("num_offset_meq_32  Max %d passed value %d\n",
		IPA_IPFLTR_NUM_MEQ_32_EQNS, attrib->num_offset_meq_32);
		return -EPERM;
	}

	for (i = 0; i < attrib->num_offset_meq_32; i++) {
		pr_err(
			   "(ofst_meq32: ofst:%u mask:0x%x val:0x%x) ",
@@ -635,6 +651,12 @@ static int ipa_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib)
				attrib->ihl_offset_eq_16.value);
	}

	if (attrib->num_ihl_offset_meq_32 > IPA_IPFLTR_NUM_IHL_MEQ_32_EQNS) {
		IPAERR_RL("num_ihl_offset_meq_32  Max %d passed value %d\n",
		IPA_IPFLTR_NUM_IHL_MEQ_32_EQNS, attrib->num_ihl_offset_meq_32);
		return -EPERM;
	}

	for (i = 0; i < attrib->num_ihl_offset_meq_32; i++) {
		pr_err(
				"(ihl_ofst_meq32: ofts:%d mask:0x%x val:0x%x) ",
@@ -643,6 +665,12 @@ static int ipa_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib)
				attrib->ihl_offset_meq_32[i].value);
	}

	if (attrib->num_offset_meq_128 > IPA_IPFLTR_NUM_MEQ_128_EQNS) {
		IPAERR_RL("num_offset_meq_128  Max %d passed value %d\n",
		IPA_IPFLTR_NUM_MEQ_128_EQNS, attrib->num_offset_meq_128);
		return -EPERM;
	}

	for (i = 0; i < attrib->num_offset_meq_128; i++) {
		for (j = 0; j < 16; j++) {
			addr[j] = attrib->offset_meq_128[i].value[j];
@@ -812,11 +840,14 @@ static ssize_t ipa_read_flt(struct file *file, char __user *ubuf, size_t count,
	u32 rt_tbl_idx;
	u32 bitmap;
	bool eq;
	int res = 0;

	tbl = &ipa_ctx->glob_flt_tbl[ip];
	mutex_lock(&ipa_ctx->lock);
	i = 0;
	list_for_each_entry(entry, &tbl->head_flt_rule_list, link) {
		if (entry->cookie != IPA_FLT_COOKIE)
			continue;
		if (entry->rule.eq_attrib_type) {
			rt_tbl_idx = entry->rule.rt_tbl_idx;
			bitmap = entry->rule.eq_attrib.rule_eq_bitmap;
@@ -835,10 +866,14 @@ static ssize_t ipa_read_flt(struct file *file, char __user *ubuf, size_t count,
			i, entry->rule.action, rt_tbl_idx);
		pr_err("attrib_mask:%08x retain_hdr:%d eq:%d ",
			bitmap, entry->rule.retain_hdr, eq);
		if (eq)
			ipa_attrib_dump_eq(
		if (eq) {
			res = ipa_attrib_dump_eq(
				&entry->rule.eq_attrib);
		else
			if (res) {
				IPAERR_RL("failed read attrib eq\n");
				goto bail;
			}
		} else
			ipa_attrib_dump(
				&entry->rule.attrib, ip);
		i++;
@@ -848,6 +883,8 @@ static ssize_t ipa_read_flt(struct file *file, char __user *ubuf, size_t count,
		tbl = &ipa_ctx->flt_tbl[j][ip];
		i = 0;
		list_for_each_entry(entry, &tbl->head_flt_rule_list, link) {
			if (entry->cookie != IPA_FLT_COOKIE)
				continue;
			if (entry->rule.eq_attrib_type) {
				rt_tbl_idx = entry->rule.rt_tbl_idx;
				bitmap = entry->rule.eq_attrib.rule_eq_bitmap;
@@ -867,18 +904,23 @@ static ssize_t ipa_read_flt(struct file *file, char __user *ubuf, size_t count,
			pr_err("attrib_mask:%08x retain_hdr:%d ",
				bitmap, entry->rule.retain_hdr);
			pr_err("eq:%d ", eq);
			if (eq)
				ipa_attrib_dump_eq(
			if (eq) {
				res = ipa_attrib_dump_eq(
						&entry->rule.eq_attrib);
			else
				if (res) {
					IPAERR_RL("failed read attrib eq\n");
					goto bail;
				}
			} else
				ipa_attrib_dump(
					&entry->rule.attrib, ip);
			i++;
		}
	}
bail:
	mutex_unlock(&ipa_ctx->lock);

	return 0;
	return res;
}

static ssize_t ipa_read_stats(struct file *file, char __user *ubuf,
+65 −10
Original line number Diff line number Diff line
@@ -359,6 +359,8 @@ static ssize_t ipa3_read_hdr(struct file *file, char __user *ubuf, size_t count,

	list_for_each_entry(entry, &ipa3_ctx->hdr_tbl.head_hdr_entry_list,
			link) {
		if (entry->cookie != IPA_HDR_COOKIE)
			continue;
		nbytes = scnprintf(
			dbg_buff,
			IPA_MAX_MSG_LEN - 1,
@@ -540,6 +542,13 @@ static int ipa3_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib)
	if (attrib->protocol_eq_present)
		pr_err("protocol:%d ", attrib->protocol_eq);

	if (attrib->num_ihl_offset_range_16 >
			IPA_IPFLTR_NUM_IHL_RANGE_16_EQNS) {
		IPAERR_RL("num_ihl_offset_range_16  Max %d passed value %d\n",
			IPA_IPFLTR_NUM_IHL_RANGE_16_EQNS,
			attrib->num_ihl_offset_range_16);
		 return -EPERM;
	}
	for (i = 0; i < attrib->num_ihl_offset_range_16; i++) {
		pr_err(
			   "(ihl_ofst_range16: ofst:%u lo:%u hi:%u) ",
@@ -548,6 +557,12 @@ static int ipa3_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib)
			   attrib->ihl_offset_range_16[i].range_high);
	}

	if (attrib->num_offset_meq_32 > IPA_IPFLTR_NUM_MEQ_32_EQNS) {
		IPAERR_RL("num_offset_meq_32  Max %d passed value %d\n",
			IPA_IPFLTR_NUM_MEQ_32_EQNS, attrib->num_offset_meq_32);
		return -EPERM;
	}

	for (i = 0; i < attrib->num_offset_meq_32; i++) {
		pr_err(
			   "(ofst_meq32: ofst:%u mask:0x%x val:0x%x) ",
@@ -569,6 +584,13 @@ static int ipa3_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib)
				attrib->ihl_offset_eq_16.value);
	}

	if (attrib->num_ihl_offset_meq_32 > IPA_IPFLTR_NUM_IHL_MEQ_32_EQNS) {
		IPAERR_RL("num_ihl_offset_meq_32  Max %d passed value %d\n",
			IPA_IPFLTR_NUM_IHL_MEQ_32_EQNS,
			attrib->num_ihl_offset_meq_32);
		return -EPERM;
	}

	for (i = 0; i < attrib->num_ihl_offset_meq_32; i++) {
		pr_err(
				"(ihl_ofst_meq32: ofts:%d mask:0x%x val:0x%x) ",
@@ -577,6 +599,12 @@ static int ipa3_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib)
				attrib->ihl_offset_meq_32[i].value);
	}

	if (attrib->num_offset_meq_128 > IPA_IPFLTR_NUM_MEQ_128_EQNS) {
		IPAERR_RL("num_offset_meq_128  Max %d passed value %d\n",
		IPA_IPFLTR_NUM_MEQ_128_EQNS, attrib->num_offset_meq_128);
		return -EPERM;
	}

	for (i = 0; i < attrib->num_offset_meq_128; i++) {
		for (j = 0; j < 16; j++) {
			addr[j] = attrib->offset_meq_128[i].value[j];
@@ -713,6 +741,7 @@ static ssize_t ipa3_read_rt_hw(struct file *file, char __user *ubuf,
	struct ipa3_debugfs_rt_entry *entry;
	enum ipa_ip_type ip = (enum ipa_ip_type)file->private_data;
	int num_tbls;
	int res = 0;

	if (ip == IPA_IP_v4)
		num_tbls = IPA_MEM_PART(v4_rt_num_index);
@@ -745,7 +774,11 @@ static ssize_t ipa3_read_rt_hw(struct file *file, char __user *ubuf,
			pr_err("rule_id:%u prio:%u retain_hdr:%u ",
				entry[i].rule_id, entry[i].prio,
				entry[i].retain_hdr);
			ipa3_attrib_dump_eq(&entry[i].eq_attrib);
			res = ipa3_attrib_dump_eq(&entry[i].eq_attrib);
			if (res) {
				IPAERR_RL("failed read attrib eq\n");
				goto bail;
			}
		}

		pr_err("== HASHABLE TABLE tbl:%d ==\n", j);
@@ -767,14 +800,20 @@ static ssize_t ipa3_read_rt_hw(struct file *file, char __user *ubuf,
			pr_err("rule_id:%u prio:%u retain_hdr:%u ",
				entry[i].rule_id, entry[i].prio,
				entry[i].retain_hdr);
			ipa3_attrib_dump_eq(&entry[i].eq_attrib);
			res = ipa3_attrib_dump_eq(&entry[i].eq_attrib);
			if (res) {
				IPAERR_RL("failed read attrib eq\n");
				goto bail;
			}
		}
	}

bail:
	mutex_unlock(&ipa3_ctx->lock);
	kfree(entry);
	IPA_ACTIVE_CLIENTS_DEC_SIMPLE();

	return 0;
	return res;
}

static ssize_t ipa3_read_proc_ctx(struct file *file, char __user *ubuf,
@@ -839,6 +878,7 @@ static ssize_t ipa3_read_flt(struct file *file, char __user *ubuf, size_t count,
	u32 rt_tbl_idx;
	u32 bitmap;
	bool eq;
	int res = 0;

	mutex_lock(&ipa3_ctx->lock);

@@ -869,18 +909,23 @@ static ssize_t ipa3_read_flt(struct file *file, char __user *ubuf, size_t count,
			pr_err("hashable:%u rule_id:%u max_prio:%u prio:%u ",
				entry->rule.hashable, entry->rule_id,
				entry->rule.max_prio, entry->prio);
			if (eq)
				ipa3_attrib_dump_eq(
			if (eq) {
				res = ipa3_attrib_dump_eq(
					&entry->rule.eq_attrib);
			else
				if (res) {
					IPAERR_RL("failed read attrib eq\n");
					goto bail;
				}
			} else
				ipa3_attrib_dump(
					&entry->rule.attrib, ip);
			i++;
		}
	}
bail:
	mutex_unlock(&ipa3_ctx->lock);

	return 0;
	return res;
}

static ssize_t ipa3_read_flt_hw(struct file *file, char __user *ubuf,
@@ -893,6 +938,7 @@ static ssize_t ipa3_read_flt_hw(struct file *file, char __user *ubuf,
	enum ipa_ip_type ip = (enum ipa_ip_type)file->private_data;
	u32 rt_tbl_idx;
	u32 bitmap;
	int res = 0;

	entry = kzalloc(sizeof(*entry) * IPA_DBG_MAX_RULE_IN_TBL, GFP_KERNEL);
	if (!entry)
@@ -915,7 +961,11 @@ static ssize_t ipa3_read_flt_hw(struct file *file, char __user *ubuf,
				bitmap, entry[i].rule.retain_hdr);
			pr_err("rule_id:%u prio:%u ",
				entry[i].rule_id, entry[i].prio);
			ipa3_attrib_dump_eq(&entry[i].rule.eq_attrib);
			res = ipa3_attrib_dump_eq(&entry[i].rule.eq_attrib);
			if (res) {
				IPAERR_RL("failed read attrib eq\n");
				goto bail;
			}
		}

		pr_err("== HASHABLE TABLE ep:%d ==\n", j);
@@ -931,14 +981,19 @@ static ssize_t ipa3_read_flt_hw(struct file *file, char __user *ubuf,
			pr_err("rule_id:%u max_prio:%u prio:%u ",
				entry[i].rule_id,
				entry[i].rule.max_prio, entry[i].prio);
			ipa3_attrib_dump_eq(&entry[i].rule.eq_attrib);
			res = ipa3_attrib_dump_eq(&entry[i].rule.eq_attrib);
			if (res) {
				IPAERR_RL("failed read attrib eq\n");
				goto bail;
			}
		}
	}
bail:
	mutex_unlock(&ipa3_ctx->lock);
	kfree(entry);
	IPA_ACTIVE_CLIENTS_DEC_SIMPLE();

	return 0;
	return res;
}

static ssize_t ipa3_read_stats(struct file *file, char __user *ubuf,