mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2024-12-22 06:04:57 -05:00
383 lines
11 KiB
Diff
383 lines
11 KiB
Diff
From d12370c7f3ecded1867fbd6b70ded35db55cab1d Mon Sep 17 00:00:00 2001
|
|
From: Skylar Chang <chiaweic@codeaurora.org>
|
|
Date: Wed, 19 Oct 2016 13:30:44 -0700
|
|
Subject: msm: ipa: fix ioctl input param validation
|
|
|
|
Fix input parameter validation in order to avoid
|
|
device crash because of incorrect parameter in IPA driver.
|
|
|
|
Change-Id: Icbdb05aeb9211665420a872d3453dbbd24fd347b
|
|
CRs-Fixed: 1069060
|
|
Acked-by: Ady Abraham <adya@qti.qualcomm.com>
|
|
Signed-off-by: Skylar Chang <chiaweic@codeaurora.org>
|
|
---
|
|
drivers/platform/msm/ipa/ipa_v2/ipa_flt.c | 36 ++++++++++++---
|
|
drivers/platform/msm/ipa/ipa_v2/ipa_i.h | 2 +-
|
|
drivers/platform/msm/ipa/ipa_v2/ipa_nat.c | 77 ++++++++++++++++++++++++++++++-
|
|
drivers/platform/msm/ipa/ipa_v2/ipa_rt.c | 26 +++++++++--
|
|
drivers/platform/msm/ipa/ipa_v3/ipa_nat.c | 76 ++++++++++++++++++++++++++++++
|
|
5 files changed, 205 insertions(+), 12 deletions(-)
|
|
|
|
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_flt.c b/drivers/platform/msm/ipa/ipa_v2/ipa_flt.c
|
|
index c36ecfe..d6e563b 100644
|
|
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_flt.c
|
|
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_flt.c
|
|
@@ -1,4 +1,4 @@
|
|
-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
|
|
+/* Copyright (c) 2012-2016, 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
|
|
@@ -235,7 +235,7 @@ static int ipa_generate_flt_hw_rule(enum ipa_ip_type ip,
|
|
* @ip: the ip address family type
|
|
* @hdr_sz: header size
|
|
*
|
|
- * Returns: 0 on success, negative on failure
|
|
+ * Returns: size on success, negative on failure
|
|
*
|
|
* caller needs to hold any needed locks to ensure integrity
|
|
*
|
|
@@ -373,7 +373,12 @@ static int ipa_generate_flt_hw_tbl_common(enum ipa_ip_type ip, u8 *base,
|
|
((long)body &
|
|
IPA_FLT_ENTRY_MEMORY_ALLIGNMENT));
|
|
} else {
|
|
- WARN_ON(tbl->sz == 0);
|
|
+ if (tbl->sz == 0) {
|
|
+ IPAERR("tbl size is 0\n");
|
|
+ WARN_ON(1);
|
|
+ goto proc_err;
|
|
+ }
|
|
+
|
|
/* allocate memory for the flt tbl */
|
|
flt_tbl_mem.size = tbl->sz;
|
|
flt_tbl_mem.base =
|
|
@@ -460,7 +465,12 @@ static int ipa_generate_flt_hw_tbl_common(enum ipa_ip_type ip, u8 *base,
|
|
((long)body &
|
|
IPA_FLT_ENTRY_MEMORY_ALLIGNMENT));
|
|
} else {
|
|
- WARN_ON(tbl->sz == 0);
|
|
+ if (tbl->sz == 0) {
|
|
+ IPAERR("tbl size is 0\n");
|
|
+ WARN_ON(1);
|
|
+ goto proc_err;
|
|
+ }
|
|
+
|
|
/* allocate memory for the flt tbl */
|
|
flt_tbl_mem.size = tbl->sz;
|
|
flt_tbl_mem.base =
|
|
@@ -534,8 +544,15 @@ static int ipa_generate_flt_hw_tbl_v1_1(enum ipa_ip_type ip,
|
|
u8 *hdr;
|
|
u8 *body;
|
|
u8 *base;
|
|
+ int res;
|
|
+
|
|
+ res = ipa_get_flt_hw_tbl_size(ip, &hdr_sz);
|
|
+ if (res < 0) {
|
|
+ IPAERR("ipa_get_flt_hw_tbl_size failed %d\n", res);
|
|
+ return res;
|
|
+ }
|
|
|
|
- mem->size = ipa_get_flt_hw_tbl_size(ip, &hdr_sz);
|
|
+ mem->size = res;
|
|
mem->size = IPA_HW_TABLE_ALIGNMENT(mem->size);
|
|
|
|
if (mem->size == 0) {
|
|
@@ -720,6 +737,7 @@ static int ipa_generate_flt_hw_tbl_v2(enum ipa_ip_type ip,
|
|
u32 *entr;
|
|
u32 body_start_offset;
|
|
u32 hdr_top;
|
|
+ int res;
|
|
|
|
if (ip == IPA_IP_v4)
|
|
body_start_offset = IPA_MEM_PART(apps_v4_flt_ofst) -
|
|
@@ -756,7 +774,13 @@ static int ipa_generate_flt_hw_tbl_v2(enum ipa_ip_type ip,
|
|
entr++;
|
|
}
|
|
|
|
- mem->size = ipa_get_flt_hw_tbl_size(ip, &hdr_sz);
|
|
+ res = ipa_get_flt_hw_tbl_size(ip, &hdr_sz);
|
|
+ if (res < 0) {
|
|
+ IPAERR("ipa_get_flt_hw_tbl_size failed %d\n", res);
|
|
+ goto body_err;
|
|
+ }
|
|
+
|
|
+ mem->size = res;
|
|
mem->size -= hdr_sz;
|
|
mem->size = IPA_HW_TABLE_ALIGNMENT(mem->size);
|
|
|
|
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
|
|
index ba16682..1e3c098 100644
|
|
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
|
|
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
|
|
@@ -137,7 +137,7 @@
|
|
|
|
#define IPA_HW_TABLE_ALIGNMENT(start_ofst) \
|
|
(((start_ofst) + 127) & ~127)
|
|
-#define IPA_RT_FLT_HW_RULE_BUF_SIZE (128)
|
|
+#define IPA_RT_FLT_HW_RULE_BUF_SIZE (256)
|
|
|
|
#define IPA_HDR_PROC_CTX_TABLE_ALIGNMENT_BYTE 8
|
|
#define IPA_HDR_PROC_CTX_TABLE_ALIGNMENT(start_ofst) \
|
|
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c b/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c
|
|
index 6202992..314b095 100644
|
|
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c
|
|
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c
|
|
@@ -1,4 +1,4 @@
|
|
-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
|
|
+/* Copyright (c) 2012-2016, 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
|
|
@@ -25,6 +25,16 @@
|
|
#define IPA_NAT_SHARED_MEMORY 1
|
|
#define IPA_NAT_TEMP_MEM_SIZE 128
|
|
|
|
+enum nat_table_type {
|
|
+ IPA_NAT_BASE_TBL = 0,
|
|
+ IPA_NAT_EXPN_TBL = 1,
|
|
+ IPA_NAT_INDX_TBL = 2,
|
|
+ IPA_NAT_INDEX_EXPN_TBL = 3,
|
|
+};
|
|
+
|
|
+#define NAT_TABLE_ENTRY_SIZE_BYTE 32
|
|
+#define NAT_INTEX_TABLE_ENTRY_SIZE_BYTE 4
|
|
+
|
|
static int ipa_nat_vma_fault_remap(
|
|
struct vm_area_struct *vma, struct vm_fault *vmf)
|
|
{
|
|
@@ -568,6 +578,71 @@ int ipa2_nat_dma_cmd(struct ipa_ioc_nat_dma_cmd *dma)
|
|
goto bail;
|
|
}
|
|
|
|
+ for (cnt = 0; cnt < dma->entries; cnt++) {
|
|
+ if (dma->dma[cnt].table_index >= 1) {
|
|
+ IPAERR("Invalid table index %d\n",
|
|
+ dma->dma[cnt].table_index);
|
|
+ ret = -EPERM;
|
|
+ goto bail;
|
|
+ }
|
|
+
|
|
+ switch (dma->dma[cnt].base_addr) {
|
|
+ case IPA_NAT_BASE_TBL:
|
|
+ if (dma->dma[cnt].offset >=
|
|
+ (ipa_ctx->nat_mem.size_base_tables + 1) *
|
|
+ NAT_TABLE_ENTRY_SIZE_BYTE) {
|
|
+ IPAERR("Invalid offset %d\n",
|
|
+ dma->dma[cnt].offset);
|
|
+ ret = -EPERM;
|
|
+ goto bail;
|
|
+ }
|
|
+
|
|
+ break;
|
|
+
|
|
+ case IPA_NAT_EXPN_TBL:
|
|
+ if (dma->dma[cnt].offset >=
|
|
+ ipa_ctx->nat_mem.size_expansion_tables *
|
|
+ NAT_TABLE_ENTRY_SIZE_BYTE) {
|
|
+ IPAERR("Invalid offset %d\n",
|
|
+ dma->dma[cnt].offset);
|
|
+ ret = -EPERM;
|
|
+ goto bail;
|
|
+ }
|
|
+
|
|
+ break;
|
|
+
|
|
+ case IPA_NAT_INDX_TBL:
|
|
+ if (dma->dma[cnt].offset >=
|
|
+ (ipa_ctx->nat_mem.size_base_tables + 1) *
|
|
+ NAT_INTEX_TABLE_ENTRY_SIZE_BYTE) {
|
|
+ IPAERR("Invalid offset %d\n",
|
|
+ dma->dma[cnt].offset);
|
|
+ ret = -EPERM;
|
|
+ goto bail;
|
|
+ }
|
|
+
|
|
+ break;
|
|
+
|
|
+ case IPA_NAT_INDEX_EXPN_TBL:
|
|
+ if (dma->dma[cnt].offset >=
|
|
+ ipa_ctx->nat_mem.size_expansion_tables *
|
|
+ NAT_INTEX_TABLE_ENTRY_SIZE_BYTE) {
|
|
+ IPAERR("Invalid offset %d\n",
|
|
+ dma->dma[cnt].offset);
|
|
+ ret = -EPERM;
|
|
+ goto bail;
|
|
+ }
|
|
+
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ IPAERR("Invalid base_addr %d\n",
|
|
+ dma->dma[cnt].base_addr);
|
|
+ ret = -EPERM;
|
|
+ goto bail;
|
|
+ }
|
|
+ }
|
|
+
|
|
size = sizeof(struct ipa_desc) * NUM_OF_DESC;
|
|
desc = kzalloc(size, GFP_KERNEL);
|
|
if (desc == NULL) {
|
|
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c
|
|
index 4ec43dd..8efc2d8 100644
|
|
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c
|
|
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c
|
|
@@ -227,7 +227,7 @@ int __ipa_generate_rt_hw_rule_v2_6L(enum ipa_ip_type ip,
|
|
* @hdr_sz: header size
|
|
* @max_rt_idx: maximal index
|
|
*
|
|
- * Returns: 0 on success, negative on failure
|
|
+ * Returns: size on success, negative on failure
|
|
*
|
|
* caller needs to hold any needed locks to ensure integrity
|
|
*
|
|
@@ -356,7 +356,11 @@ static int ipa_generate_rt_hw_tbl_common(enum ipa_ip_type ip, u8 *base, u8 *hdr,
|
|
((long)body &
|
|
IPA_RT_ENTRY_MEMORY_ALLIGNMENT));
|
|
} else {
|
|
- WARN_ON(tbl->sz == 0);
|
|
+ if (tbl->sz == 0) {
|
|
+ IPAERR("cannot generate 0 size table\n");
|
|
+ goto proc_err;
|
|
+ }
|
|
+
|
|
/* allocate memory for the RT tbl */
|
|
rt_tbl_mem.size = tbl->sz;
|
|
rt_tbl_mem.base =
|
|
@@ -429,8 +433,15 @@ static int ipa_generate_rt_hw_tbl_v1_1(enum ipa_ip_type ip,
|
|
u8 *base;
|
|
int max_rt_idx;
|
|
int i;
|
|
+ int res;
|
|
|
|
- mem->size = ipa_get_rt_hw_tbl_size(ip, &hdr_sz, &max_rt_idx);
|
|
+ res = ipa_get_rt_hw_tbl_size(ip, &hdr_sz, &max_rt_idx);
|
|
+ if (res < 0) {
|
|
+ IPAERR("ipa_get_rt_hw_tbl_size failed %d\n", res);
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
+ mem->size = res;
|
|
mem->size = (mem->size + IPA_RT_TABLE_MEMORY_ALLIGNMENT) &
|
|
~IPA_RT_TABLE_MEMORY_ALLIGNMENT;
|
|
|
|
@@ -603,6 +614,7 @@ static int ipa_generate_rt_hw_tbl_v2(enum ipa_ip_type ip,
|
|
int num_index;
|
|
u32 body_start_offset;
|
|
u32 apps_start_idx;
|
|
+ int res;
|
|
|
|
if (ip == IPA_IP_v4) {
|
|
num_index = IPA_MEM_PART(v4_apps_rt_index_hi) -
|
|
@@ -632,7 +644,13 @@ static int ipa_generate_rt_hw_tbl_v2(enum ipa_ip_type ip,
|
|
entr++;
|
|
}
|
|
|
|
- mem->size = ipa_get_rt_hw_tbl_size(ip, &hdr_sz, &max_rt_idx);
|
|
+ res = ipa_get_rt_hw_tbl_size(ip, &hdr_sz, &max_rt_idx);
|
|
+ if (res < 0) {
|
|
+ IPAERR("ipa_get_rt_hw_tbl_size failed %d\n", res);
|
|
+ goto base_err;
|
|
+ }
|
|
+
|
|
+ mem->size = res;
|
|
mem->size -= hdr_sz;
|
|
mem->size = (mem->size + IPA_RT_TABLE_MEMORY_ALLIGNMENT) &
|
|
~IPA_RT_TABLE_MEMORY_ALLIGNMENT;
|
|
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c b/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c
|
|
index 67e9b39..e7e5cf1 100644
|
|
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c
|
|
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c
|
|
@@ -24,6 +24,17 @@
|
|
|
|
#define IPA_NAT_TEMP_MEM_SIZE 128
|
|
|
|
+enum nat_table_type {
|
|
+ IPA_NAT_BASE_TBL = 0,
|
|
+ IPA_NAT_EXPN_TBL = 1,
|
|
+ IPA_NAT_INDX_TBL = 2,
|
|
+ IPA_NAT_INDEX_EXPN_TBL = 3,
|
|
+};
|
|
+
|
|
+#define NAT_TABLE_ENTRY_SIZE_BYTE 32
|
|
+#define NAT_INTEX_TABLE_ENTRY_SIZE_BYTE 4
|
|
+
|
|
+
|
|
static int ipa3_nat_vma_fault_remap(
|
|
struct vm_area_struct *vma, struct vm_fault *vmf)
|
|
{
|
|
@@ -571,6 +582,71 @@ int ipa3_nat_dma_cmd(struct ipa_ioc_nat_dma_cmd *dma)
|
|
goto bail;
|
|
}
|
|
|
|
+ for (cnt = 0; cnt < dma->entries; cnt++) {
|
|
+ if (dma->dma[cnt].table_index >= 1) {
|
|
+ IPAERR("Invalid table index %d\n",
|
|
+ dma->dma[cnt].table_index);
|
|
+ ret = -EPERM;
|
|
+ goto bail;
|
|
+ }
|
|
+
|
|
+ switch (dma->dma[cnt].base_addr) {
|
|
+ case IPA_NAT_BASE_TBL:
|
|
+ if (dma->dma[cnt].offset >=
|
|
+ (ipa3_ctx->nat_mem.size_base_tables + 1) *
|
|
+ NAT_TABLE_ENTRY_SIZE_BYTE) {
|
|
+ IPAERR("Invalid offset %d\n",
|
|
+ dma->dma[cnt].offset);
|
|
+ ret = -EPERM;
|
|
+ goto bail;
|
|
+ }
|
|
+
|
|
+ break;
|
|
+
|
|
+ case IPA_NAT_EXPN_TBL:
|
|
+ if (dma->dma[cnt].offset >=
|
|
+ ipa3_ctx->nat_mem.size_expansion_tables *
|
|
+ NAT_TABLE_ENTRY_SIZE_BYTE) {
|
|
+ IPAERR("Invalid offset %d\n",
|
|
+ dma->dma[cnt].offset);
|
|
+ ret = -EPERM;
|
|
+ goto bail;
|
|
+ }
|
|
+
|
|
+ break;
|
|
+
|
|
+ case IPA_NAT_INDX_TBL:
|
|
+ if (dma->dma[cnt].offset >=
|
|
+ (ipa3_ctx->nat_mem.size_base_tables + 1) *
|
|
+ NAT_INTEX_TABLE_ENTRY_SIZE_BYTE) {
|
|
+ IPAERR("Invalid offset %d\n",
|
|
+ dma->dma[cnt].offset);
|
|
+ ret = -EPERM;
|
|
+ goto bail;
|
|
+ }
|
|
+
|
|
+ break;
|
|
+
|
|
+ case IPA_NAT_INDEX_EXPN_TBL:
|
|
+ if (dma->dma[cnt].offset >=
|
|
+ ipa3_ctx->nat_mem.size_expansion_tables *
|
|
+ NAT_INTEX_TABLE_ENTRY_SIZE_BYTE) {
|
|
+ IPAERR("Invalid offset %d\n",
|
|
+ dma->dma[cnt].offset);
|
|
+ ret = -EPERM;
|
|
+ goto bail;
|
|
+ }
|
|
+
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ IPAERR("Invalid base_addr %d\n",
|
|
+ dma->dma[cnt].base_addr);
|
|
+ ret = -EPERM;
|
|
+ goto bail;
|
|
+ }
|
|
+ }
|
|
+
|
|
size = sizeof(struct ipa3_desc) * NUM_OF_DESC;
|
|
desc = kzalloc(size, GFP_KERNEL);
|
|
if (desc == NULL) {
|
|
--
|
|
cgit v1.1
|
|
|