msm: ipa3: Fix to validate the user inputs

Adding code changes to validate user inputs.
Before allocating the NAT entry verifying the
NAT entry size in range or not.

Change-Id: I47b97973a3ea66b1627a323f77778b295c7765a4
Acked-by: Ashok Vuyyuru <avuyyuru@qti.qualcomm.com>
Signed-off-by: Mohammed Javid <mjavid@codeaurora.org>
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c b/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c
index c2daa05..19d3d30 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -31,6 +31,13 @@
 #define IPA_IPV6CT_MAX_NUM_OF_INIT_CMD_DESC 2
 #define IPA_MAX_NUM_OF_TABLE_DMA_CMD_DESC 4
 
+/*
+ * The base table max entries is limited by index into table 13 bits number.
+ * Limit the memory size required by user to prevent kernel memory starvation
+ */
+#define IPA_TABLE_MAX_ENTRIES 8192
+#define MAX_ALLOC_NAT_SIZE(size) (IPA_TABLE_MAX_ENTRIES * size)
+
 enum ipa_nat_ipv6ct_table_type {
 	IPA_NAT_BASE_TBL = 0,
 	IPA_NAT_EXPN_TBL = 1,
@@ -338,10 +345,12 @@
 }
 
 static int ipa3_nat_ipv6ct_allocate_mem(struct ipa3_nat_ipv6ct_common_mem *dev,
-	struct ipa_ioc_nat_ipv6ct_table_alloc *table_alloc)
+	struct ipa_ioc_nat_ipv6ct_table_alloc *table_alloc,
+	enum ipahal_nat_type nat_type)
 {
 	gfp_t gfp_flags = GFP_KERNEL | __GFP_ZERO;
 	int result = 0;
+	size_t nat_entry_size;
 
 	IPADBG("passed memory size %zu for %s\n",
 		table_alloc->size, dev->name);
@@ -358,6 +367,15 @@
 		goto bail;
 	}
 
+	ipahal_nat_entry_size(nat_type, &nat_entry_size);
+	if (table_alloc->size > MAX_ALLOC_NAT_SIZE(nat_entry_size)) {
+		IPAERR("Trying allocate more size = %zu, Max allowed = %zu\n",
+				table_alloc->size,
+				MAX_ALLOC_NAT_SIZE(nat_entry_size));
+		result = -EPERM;
+		goto bail;
+	}
+
 	if (!table_alloc->size) {
 		IPAERR_RL("Invalid Parameters\n");
 		result = -EPERM;
@@ -433,7 +451,8 @@
 
 	mutex_lock(&nat_ctx->dev.lock);
 
-	result = ipa3_nat_ipv6ct_allocate_mem(&nat_ctx->dev, table_alloc);
+	result = ipa3_nat_ipv6ct_allocate_mem(&nat_ctx->dev, table_alloc,
+							IPAHAL_NAT_IPV4);
 	if (result)
 		goto bail;
 
@@ -507,7 +526,7 @@
 	mutex_lock(&ipa3_ctx->ipv6ct_mem.dev.lock);
 
 	result = ipa3_nat_ipv6ct_allocate_mem(
-		&ipa3_ctx->ipv6ct_mem.dev, table_alloc);
+		&ipa3_ctx->ipv6ct_mem.dev, table_alloc, IPAHAL_NAT_IPV6CT);
 	if (result)
 		goto bail;