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

Commit bb49c0b2 authored by Mohammed Javid's avatar Mohammed Javid Committed by Gerrit - the friendly Code Review server
Browse files

msm: ipa3: Add mutex to prevent race condition



There is a race condition between ipa3_nat_init_cmd
and ipa_read_nat4. The two thread will R/W the critical
global variables. This will result in race conditions
and possibly buffer overread/ overwrite issues. Add code
to prevent this race condition.

Change-Id: I6bf9a837ae941cf3ad9413da6e44821916acf196
Acked-by: default avatarPooja Kumari <kumarip@qti.qualcomm.com>
Signed-off-by: default avatarMohammed Javid <mjavid@codeaurora.org>
parent 387632bf
Loading
Loading
Loading
Loading
+13 −0
Original line number Original line Diff line number Diff line
@@ -327,14 +327,18 @@ int ipa2_nat_init_cmd(struct ipa_ioc_v4_nat_init *init)
	size_t tmp;
	size_t tmp;
	gfp_t flag = GFP_KERNEL | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);
	gfp_t flag = GFP_KERNEL | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);


	mutex_lock(&ipa_ctx->nat_mem.lock);

	if (!ipa_ctx->nat_mem.is_dev_init) {
	if (!ipa_ctx->nat_mem.is_dev_init) {
		IPAERR_RL("Nat table not initialized\n");
		IPAERR_RL("Nat table not initialized\n");
		mutex_unlock(&ipa_ctx->nat_mem.lock);
		return -EPERM;
		return -EPERM;
	}
	}


	IPADBG("\n");
	IPADBG("\n");
	if (init->table_entries == 0) {
	if (init->table_entries == 0) {
		IPADBG("Table entries is zero\n");
		IPADBG("Table entries is zero\n");
		mutex_unlock(&ipa_ctx->nat_mem.lock);
		return -EPERM;
		return -EPERM;
	}
	}


@@ -342,6 +346,7 @@ int ipa2_nat_init_cmd(struct ipa_ioc_v4_nat_init *init)
	if (init->ipv4_rules_offset >
	if (init->ipv4_rules_offset >
		(UINT_MAX - (TBL_ENTRY_SIZE * (init->table_entries + 1)))) {
		(UINT_MAX - (TBL_ENTRY_SIZE * (init->table_entries + 1)))) {
		IPAERR_RL("Detected overflow\n");
		IPAERR_RL("Detected overflow\n");
		mutex_unlock(&ipa_ctx->nat_mem.lock);
		return -EPERM;
		return -EPERM;
	}
	}
	/* Check Table Entry offset is not
	/* Check Table Entry offset is not
@@ -354,6 +359,7 @@ int ipa2_nat_init_cmd(struct ipa_ioc_v4_nat_init *init)
		IPAERR_RL("offset:%d entrys:%d size:%zu mem_size:%zu\n",
		IPAERR_RL("offset:%d entrys:%d size:%zu mem_size:%zu\n",
			init->ipv4_rules_offset, (init->table_entries + 1),
			init->ipv4_rules_offset, (init->table_entries + 1),
			tmp, ipa_ctx->nat_mem.size);
			tmp, ipa_ctx->nat_mem.size);
		mutex_unlock(&ipa_ctx->nat_mem.lock);
		return -EPERM;
		return -EPERM;
	}
	}


@@ -361,6 +367,7 @@ int ipa2_nat_init_cmd(struct ipa_ioc_v4_nat_init *init)
	if (init->expn_rules_offset >
	if (init->expn_rules_offset >
		UINT_MAX - (TBL_ENTRY_SIZE * init->expn_table_entries)) {
		UINT_MAX - (TBL_ENTRY_SIZE * init->expn_table_entries)) {
		IPAERR_RL("Detected overflow\n");
		IPAERR_RL("Detected overflow\n");
		mutex_unlock(&ipa_ctx->nat_mem.lock);
		return -EPERM;
		return -EPERM;
	}
	}
	/* Check Expn Table Entry offset is not
	/* Check Expn Table Entry offset is not
@@ -373,6 +380,7 @@ int ipa2_nat_init_cmd(struct ipa_ioc_v4_nat_init *init)
		IPAERR_RL("offset:%d entrys:%d size:%zu mem_size:%zu\n",
		IPAERR_RL("offset:%d entrys:%d size:%zu mem_size:%zu\n",
			init->expn_rules_offset, init->expn_table_entries,
			init->expn_rules_offset, init->expn_table_entries,
			tmp, ipa_ctx->nat_mem.size);
			tmp, ipa_ctx->nat_mem.size);
		mutex_unlock(&ipa_ctx->nat_mem.lock);
		return -EPERM;
		return -EPERM;
	}
	}


@@ -380,6 +388,7 @@ int ipa2_nat_init_cmd(struct ipa_ioc_v4_nat_init *init)
	if (init->index_offset >
	if (init->index_offset >
		UINT_MAX - (INDX_TBL_ENTRY_SIZE * (init->table_entries + 1))) {
		UINT_MAX - (INDX_TBL_ENTRY_SIZE * (init->table_entries + 1))) {
		IPAERR_RL("Detected overflow\n");
		IPAERR_RL("Detected overflow\n");
		mutex_unlock(&ipa_ctx->nat_mem.lock);
		return -EPERM;
		return -EPERM;
	}
	}
	/* Check Indx Table Entry offset is not
	/* Check Indx Table Entry offset is not
@@ -392,6 +401,7 @@ int ipa2_nat_init_cmd(struct ipa_ioc_v4_nat_init *init)
		IPAERR_RL("offset:%d entrys:%d size:%zu mem_size:%zu\n",
		IPAERR_RL("offset:%d entrys:%d size:%zu mem_size:%zu\n",
			init->index_offset, (init->table_entries + 1),
			init->index_offset, (init->table_entries + 1),
			tmp, ipa_ctx->nat_mem.size);
			tmp, ipa_ctx->nat_mem.size);
		mutex_unlock(&ipa_ctx->nat_mem.lock);
		return -EPERM;
		return -EPERM;
	}
	}


@@ -399,6 +409,7 @@ int ipa2_nat_init_cmd(struct ipa_ioc_v4_nat_init *init)
	if (init->index_expn_offset >
	if (init->index_expn_offset >
		(UINT_MAX - (INDX_TBL_ENTRY_SIZE * init->expn_table_entries))) {
		(UINT_MAX - (INDX_TBL_ENTRY_SIZE * init->expn_table_entries))) {
		IPAERR_RL("Detected overflow\n");
		IPAERR_RL("Detected overflow\n");
		mutex_unlock(&ipa_ctx->nat_mem.lock);
		return -EPERM;
		return -EPERM;
	}
	}
	/* Check Expn Table entry offset is not
	/* Check Expn Table entry offset is not
@@ -411,6 +422,7 @@ int ipa2_nat_init_cmd(struct ipa_ioc_v4_nat_init *init)
		IPAERR_RL("offset:%d entrys:%d size:%zu mem_size:%zu\n",
		IPAERR_RL("offset:%d entrys:%d size:%zu mem_size:%zu\n",
			init->index_expn_offset, init->expn_table_entries,
			init->index_expn_offset, init->expn_table_entries,
			tmp, ipa_ctx->nat_mem.size);
			tmp, ipa_ctx->nat_mem.size);
		mutex_unlock(&ipa_ctx->nat_mem.lock);
		return -EPERM;
		return -EPERM;
	}
	}


@@ -559,6 +571,7 @@ int ipa2_nat_init_cmd(struct ipa_ioc_v4_nat_init *init)
free_nop:
free_nop:
	kfree(reg_write_nop);
	kfree(reg_write_nop);
bail:
bail:
	mutex_unlock(&ipa_ctx->nat_mem.lock);
	return result;
	return result;
}
}


+12 −0
Original line number Original line Diff line number Diff line
@@ -838,19 +838,24 @@ int ipa3_nat_init_cmd(struct ipa_ioc_v4_nat_init *init)


	IPADBG("\n");
	IPADBG("\n");


	mutex_lock(&ipa3_ctx->nat_mem.dev.lock);

	if (!ipa3_ctx->nat_mem.dev.is_mapped) {
	if (!ipa3_ctx->nat_mem.dev.is_mapped) {
		IPAERR_RL("attempt to init %s before mmap\n",
		IPAERR_RL("attempt to init %s before mmap\n",
			ipa3_ctx->nat_mem.dev.name);
			ipa3_ctx->nat_mem.dev.name);
		mutex_unlock(&ipa3_ctx->nat_mem.dev.lock);
		return -EPERM;
		return -EPERM;
	}
	}


	if (init->tbl_index >= 1) {
	if (init->tbl_index >= 1) {
		IPAERR_RL("Unsupported table index %d\n", init->tbl_index);
		IPAERR_RL("Unsupported table index %d\n", init->tbl_index);
		mutex_unlock(&ipa3_ctx->nat_mem.dev.lock);
		return -EPERM;
		return -EPERM;
	}
	}


	if (init->table_entries == 0) {
	if (init->table_entries == 0) {
		IPAERR_RL("Table entries is zero\n");
		IPAERR_RL("Table entries is zero\n");
		mutex_unlock(&ipa3_ctx->nat_mem.dev.lock);
		return -EPERM;
		return -EPERM;
	}
	}


@@ -861,6 +866,7 @@ int ipa3_nat_init_cmd(struct ipa_ioc_v4_nat_init *init)
		IPAHAL_NAT_IPV4);
		IPAHAL_NAT_IPV4);
	if (result) {
	if (result) {
		IPAERR_RL("Bad params for NAT base table\n");
		IPAERR_RL("Bad params for NAT base table\n");
		mutex_unlock(&ipa3_ctx->nat_mem.dev.lock);
		return result;
		return result;
	}
	}


@@ -871,6 +877,7 @@ int ipa3_nat_init_cmd(struct ipa_ioc_v4_nat_init *init)
		IPAHAL_NAT_IPV4);
		IPAHAL_NAT_IPV4);
	if (result) {
	if (result) {
		IPAERR_RL("Bad params for NAT expansion table\n");
		IPAERR_RL("Bad params for NAT expansion table\n");
		mutex_unlock(&ipa3_ctx->nat_mem.dev.lock);
		return result;
		return result;
	}
	}


@@ -881,6 +888,7 @@ int ipa3_nat_init_cmd(struct ipa_ioc_v4_nat_init *init)
		IPAHAL_NAT_IPV4_INDEX);
		IPAHAL_NAT_IPV4_INDEX);
	if (result) {
	if (result) {
		IPAERR_RL("Bad params for index table\n");
		IPAERR_RL("Bad params for index table\n");
		mutex_unlock(&ipa3_ctx->nat_mem.dev.lock);
		return result;
		return result;
	}
	}


@@ -891,6 +899,7 @@ int ipa3_nat_init_cmd(struct ipa_ioc_v4_nat_init *init)
		IPAHAL_NAT_IPV4_INDEX);
		IPAHAL_NAT_IPV4_INDEX);
	if (result) {
	if (result) {
		IPAERR_RL("Bad params for index expansion table\n");
		IPAERR_RL("Bad params for index expansion table\n");
		mutex_unlock(&ipa3_ctx->nat_mem.dev.lock);
		return result;
		return result;
	}
	}


@@ -924,6 +933,7 @@ int ipa3_nat_init_cmd(struct ipa_ioc_v4_nat_init *init)
	result = ipa3_nat_send_init_cmd(&cmd, false);
	result = ipa3_nat_send_init_cmd(&cmd, false);
	if (result) {
	if (result) {
		IPAERR("Fail to send NAT init immediate command\n");
		IPAERR("Fail to send NAT init immediate command\n");
		mutex_unlock(&ipa3_ctx->nat_mem.dev.lock);
		return result;
		return result;
	}
	}


@@ -949,6 +959,8 @@ int ipa3_nat_init_cmd(struct ipa_ioc_v4_nat_init *init)
				 ipa3_ctx->nat_mem.index_table_expansion_addr);
				 ipa3_ctx->nat_mem.index_table_expansion_addr);


	ipa3_ctx->nat_mem.dev.is_hw_init = true;
	ipa3_ctx->nat_mem.dev.is_hw_init = true;
	mutex_unlock(&ipa3_ctx->nat_mem.dev.lock);

	IPADBG("return\n");
	IPADBG("return\n");
	return 0;
	return 0;
}
}