Switch to new CVE patchset

This commit is contained in:
Tad 2017-11-07 17:32:46 -05:00
parent 57ce42402b
commit 11c7037780
1215 changed files with 60697 additions and 14533 deletions

View file

@ -0,0 +1,323 @@
From 58a0d46820909166c89286bdbffbae3358daf778 Mon Sep 17 00:00:00 2001
From: Ghanim Fodi <gfodi@codeaurora.org>
Date: Mon, 16 Jan 2017 00:17:04 +0200
Subject: msm: ipa: Prevent multiple header deletion from user space
An IPA header or processing context can be added once
and later deleted once from user space.
Multiple deletion may cause invalid state of the headers
software cache.
Change-Id: Ic0b8472b7fd8a76233a007d90c832af726184574
CRs-fixed: 1097714
Signed-off-by: Ghanim Fodi <gfodi@codeaurora.org>
---
drivers/platform/msm/ipa/ipa.c | 13 ++++---
drivers/platform/msm/ipa/ipa_hdr.c | 77 +++++++++++++++++++++++++++++++-------
drivers/platform/msm/ipa/ipa_i.h | 11 +++++-
3 files changed, 79 insertions(+), 22 deletions(-)
diff --git a/drivers/platform/msm/ipa/ipa.c b/drivers/platform/msm/ipa/ipa.c
index ddb716c..82caefc 100644
--- a/drivers/platform/msm/ipa/ipa.c
+++ b/drivers/platform/msm/ipa/ipa.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, 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
@@ -436,7 +436,8 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
retval = -EFAULT;
break;
}
- if (ipa_del_hdr((struct ipa_ioc_del_hdr *)param)) {
+ if (ipa_del_hdr_by_user((struct ipa_ioc_del_hdr *)param,
+ true)) {
retval = -EFAULT;
break;
}
@@ -1117,8 +1118,8 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
retval = -EFAULT;
break;
}
- if (ipa_del_hdr_proc_ctx(
- (struct ipa_ioc_del_hdr_proc_ctx *)param)) {
+ if (ipa_del_hdr_proc_ctx_by_user(
+ (struct ipa_ioc_del_hdr_proc_ctx *)param, true)) {
retval = -EFAULT;
break;
}
@@ -2256,7 +2257,7 @@ fail_schedule_delayed_work:
if (ipa_ctx->dflt_v4_rt_rule_hdl)
__ipa_del_rt_rule(ipa_ctx->dflt_v4_rt_rule_hdl);
if (ipa_ctx->excp_hdr_hdl)
- __ipa_del_hdr(ipa_ctx->excp_hdr_hdl);
+ __ipa_del_hdr(ipa_ctx->excp_hdr_hdl, false);
ipa_teardown_sys_pipe(ipa_ctx->clnt_hdl_cmd);
fail_cmd:
return result;
@@ -2268,7 +2269,7 @@ static void ipa_teardown_apps_pipes(void)
ipa_teardown_sys_pipe(ipa_ctx->clnt_hdl_data_in);
__ipa_del_rt_rule(ipa_ctx->dflt_v6_rt_rule_hdl);
__ipa_del_rt_rule(ipa_ctx->dflt_v4_rt_rule_hdl);
- __ipa_del_hdr(ipa_ctx->excp_hdr_hdl);
+ __ipa_del_hdr(ipa_ctx->excp_hdr_hdl, false);
ipa_teardown_sys_pipe(ipa_ctx->clnt_hdl_cmd);
}
diff --git a/drivers/platform/msm/ipa/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_hdr.c
index 67aa787..45b0ef6 100644
--- a/drivers/platform/msm/ipa/ipa_hdr.c
+++ b/drivers/platform/msm/ipa/ipa_hdr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, 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
@@ -719,7 +719,8 @@ error:
return -EPERM;
}
-static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr)
+static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl,
+ bool release_hdr, bool by_user)
{
struct ipa_hdr_proc_ctx_entry *entry;
struct ipa_hdr_proc_ctx_tbl *htbl = &ipa_ctx->hdr_proc_ctx_tbl;
@@ -733,6 +734,14 @@ static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr)
IPADBG("del ctx proc cnt=%d ofst=%d\n",
htbl->proc_ctx_cnt, entry->offset_entry->offset);
+ if (by_user && entry->user_deleted) {
+ IPAERR("proc_ctx already deleted by user\n");
+ return -EINVAL;
+ }
+
+ if (by_user)
+ entry->user_deleted = true;
+
if (--entry->ref_cnt) {
IPADBG("proc_ctx_hdl %x ref_cnt %d\n",
proc_ctx_hdl, entry->ref_cnt);
@@ -740,7 +749,7 @@ static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr)
}
if (release_hdr)
- __ipa_release_hdr(entry->hdr->id);
+ __ipa_del_hdr(entry->hdr->id, false);
/* move the offset entry to appropriate free list */
list_move(&entry->offset_entry->link,
@@ -757,7 +766,7 @@ static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr)
}
-int __ipa_del_hdr(u32 hdr_hdl)
+int __ipa_del_hdr(u32 hdr_hdl, bool by_user)
{
struct ipa_hdr_entry *entry;
struct ipa_hdr_tbl *htbl = &ipa_ctx->hdr_tbl;
@@ -776,6 +785,14 @@ int __ipa_del_hdr(u32 hdr_hdl)
IPADBG("del hdr of sz=%d hdr_cnt=%d ofst=%d\n", entry->hdr_len,
htbl->hdr_cnt, entry->offset_entry->offset);
+ if (by_user && entry->user_deleted) {
+ IPAERR("hdr already deleted by user\n");
+ return -EINVAL;
+ }
+
+ if (by_user)
+ entry->user_deleted = true;
+
if (--entry->ref_cnt) {
IPADBG("hdr_hdl %x ref_cnt %d\n", hdr_hdl, entry->ref_cnt);
return 0;
@@ -786,7 +803,7 @@ int __ipa_del_hdr(u32 hdr_hdl)
entry->phys_base,
entry->hdr_len,
DMA_TO_DEVICE);
- __ipa_del_hdr_proc_ctx(entry->proc_ctx->id, false);
+ __ipa_del_hdr_proc_ctx(entry->proc_ctx->id, false, false);
} else {
/* move the offset entry to appropriate free list */
list_move(&entry->offset_entry->link,
@@ -849,15 +866,16 @@ bail:
EXPORT_SYMBOL(ipa_add_hdr);
/**
- * ipa_del_hdr() - Remove the specified headers from SW and optionally commit them
- * to IPA HW
+ * ipa_del_hdr_by_user() - Remove the specified headers
+ * from SW and optionally commit them to IPA HW
* @hdls: [inout] set of headers to delete
+ * @by_user: Operation requested by user?
*
* Returns: 0 on success, negative on failure
*
* Note: Should not be called from atomic context
*/
-int ipa_del_hdr(struct ipa_ioc_del_hdr *hdls)
+int ipa_del_hdr_by_user(struct ipa_ioc_del_hdr *hdls, bool by_user)
{
int i;
int result = -EFAULT;
@@ -869,7 +887,7 @@ int ipa_del_hdr(struct ipa_ioc_del_hdr *hdls)
mutex_lock(&ipa_ctx->lock);
for (i = 0; i < hdls->num_hdls; i++) {
- if (__ipa_del_hdr(hdls->hdl[i].hdl)) {
+ if (__ipa_del_hdr(hdls->hdl[i].hdl, by_user)) {
IPAERR("failed to del hdr %i\n", i);
hdls->hdl[i].status = -1;
} else {
@@ -888,6 +906,20 @@ bail:
mutex_unlock(&ipa_ctx->lock);
return result;
}
+
+/**
+ * ipa_del_hdr() - Remove the specified headers from SW and optionally commit them
+ * to IPA HW
+ * @hdls: [inout] set of headers to delete
+ *
+ * Returns: 0 on success, negative on failure
+ *
+ * Note: Should not be called from atomic context
+ */
+int ipa_del_hdr(struct ipa_ioc_del_hdr *hdls)
+{
+ return ipa_del_hdr_by_user(hdls, false);
+}
EXPORT_SYMBOL(ipa_del_hdr);
/**
@@ -936,16 +968,18 @@ bail:
EXPORT_SYMBOL(ipa_add_hdr_proc_ctx);
/**
- * ipa_del_hdr_proc_ctx() -
+ * ipa_del_hdr_proc_ctx_by_user() -
* Remove the specified processing context headers from SW and
* optionally commit them to IPA HW.
* @hdls: [inout] set of processing context headers to delete
+ * @by_user: Operation requested by user?
*
* Returns: 0 on success, negative on failure
*
* Note: Should not be called from atomic context
*/
-int ipa_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls)
+int ipa_del_hdr_proc_ctx_by_user(struct ipa_ioc_del_hdr_proc_ctx *hdls,
+ bool by_user)
{
int i;
int result;
@@ -957,7 +991,7 @@ int ipa_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls)
mutex_lock(&ipa_ctx->lock);
for (i = 0; i < hdls->num_hdls; i++) {
- if (__ipa_del_hdr_proc_ctx(hdls->hdl[i].hdl, true)) {
+ if (__ipa_del_hdr_proc_ctx(hdls->hdl[i].hdl, true, by_user)) {
IPAERR("failed to del hdr %i\n", i);
hdls->hdl[i].status = -1;
} else {
@@ -976,6 +1010,21 @@ bail:
mutex_unlock(&ipa_ctx->lock);
return result;
}
+
+/**
+ * ipa_del_hdr_proc_ctx() -
+ * Remove the specified processing context headers from SW and
+ * optionally commit them to IPA HW.
+ * @hdls: [inout] set of processing context headers to delete
+ *
+ * Returns: 0 on success, negative on failure
+ *
+ * Note: Should not be called from atomic context
+ */
+int ipa_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls)
+{
+ return ipa_del_hdr_proc_ctx_by_user(hdls, false);
+}
EXPORT_SYMBOL(ipa_del_hdr_proc_ctx);
/**
@@ -1197,7 +1246,7 @@ int __ipa_release_hdr(u32 hdr_hdl)
{
int result = 0;
- if (__ipa_del_hdr(hdr_hdl)) {
+ if (__ipa_del_hdr(hdr_hdl, false)) {
IPADBG("fail to del hdr %x\n", hdr_hdl);
result = -EFAULT;
goto bail;
@@ -1225,7 +1274,7 @@ int __ipa_release_hdr_proc_ctx(u32 proc_ctx_hdl)
{
int result = 0;
- if (__ipa_del_hdr_proc_ctx(proc_ctx_hdl, true)) {
+ if (__ipa_del_hdr_proc_ctx(proc_ctx_hdl, true, false)) {
IPADBG("fail to del hdr %x\n", proc_ctx_hdl);
result = -EFAULT;
goto bail;
diff --git a/drivers/platform/msm/ipa/ipa_i.h b/drivers/platform/msm/ipa/ipa_i.h
index ed05434..c71862c 100644
--- a/drivers/platform/msm/ipa/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_i.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, 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
@@ -224,6 +224,7 @@ struct ipa_rt_tbl {
* @id: header entry id
* @is_eth2_ofst_valid: is eth2_ofst field valid?
* @eth2_ofst: offset to start of Ethernet-II/802.3 header
+ * @user_deleted: is the header deleted by the user?
*/
struct ipa_hdr_entry {
struct list_head link;
@@ -241,6 +242,7 @@ struct ipa_hdr_entry {
int id;
u8 is_eth2_ofst_valid;
u16 eth2_ofst;
+ bool user_deleted;
};
/**
@@ -316,6 +318,7 @@ struct ipa_hdr_proc_ctx_add_hdr_cmd_seq {
* @cookie: cookie used for validity check
* @ref_cnt: reference counter of routing table
* @id: processing context header entry id
+ * @user_deleted: is the hdr processing context deleted by the user?
*/
struct ipa_hdr_proc_ctx_entry {
struct list_head link;
@@ -325,6 +328,7 @@ struct ipa_hdr_proc_ctx_entry {
u32 cookie;
u32 ref_cnt;
int id;
+ bool user_deleted;
};
/**
@@ -1136,8 +1140,11 @@ void ipa_inc_client_enable_clks(void);
int ipa_inc_client_enable_clks_no_block(void);
void ipa_dec_client_disable_clks(void);
int ipa_interrupts_init(u32 ipa_irq, u32 ee, struct device *ipa_dev);
+int ipa_del_hdr_by_user(struct ipa_ioc_del_hdr *hdls, bool by_user);
+int ipa_del_hdr_proc_ctx_by_user(struct ipa_ioc_del_hdr_proc_ctx *hdls,
+ bool by_user);
int __ipa_del_rt_rule(u32 rule_hdl);
-int __ipa_del_hdr(u32 hdr_hdl);
+int __ipa_del_hdr(u32 hdr_hdl, bool by_user);
int __ipa_release_hdr(u32 hdr_hdl);
int __ipa_release_hdr_proc_ctx(u32 proc_ctx_hdl);
int _ipa_read_gen_reg_v1_0(char *buff, int max_len);
--
cgit v1.1

View file

@ -1,5 +1,5 @@
From 050ee9e77ca89e9997792a0ab371470218da9a97 Mon Sep 17 00:00:00 2001
From: Aaron Tzeng <Aaron.Tzeng@quantatw.com>
From a6a6e4993aca80b7cddab8752f7d8636eb45a8c5 Mon Sep 17 00:00:00 2001
From: Ghanim Fodi <gfodi@codeaurora.org>
Date: Thu, 12 Jan 2017 15:14:15 +0200
Subject: msm: ipa: Prevent multiple header deletion from user space
@ -21,16 +21,16 @@ Signed-off-by: Ghanim Fodi <gfodi@codeaurora.org>
6 files changed, 162 insertions(+), 44 deletions(-)
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa.c b/drivers/platform/msm/ipa/ipa_v2/ipa.c
index 393d580..011500c 100644
index 7bcb267..d6f2ce6 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa.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.
+/* Copyright (c) 2012-2017, 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
@@ -777,7 +777,8 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
@@ -734,7 +734,8 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
retval = -EINVAL;
break;
}
@ -40,7 +40,7 @@ index 393d580..011500c 100644
retval = -EFAULT;
break;
}
@@ -1461,8 +1462,8 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
@@ -1418,8 +1419,8 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
retval = -EINVAL;
break;
}
@ -51,7 +51,7 @@ index 393d580..011500c 100644
retval = -EFAULT;
break;
}
@@ -2755,7 +2756,7 @@ fail_schedule_delayed_work:
@@ -2801,7 +2802,7 @@ fail_schedule_delayed_work:
if (ipa_ctx->dflt_v4_rt_rule_hdl)
__ipa_del_rt_rule(ipa_ctx->dflt_v4_rt_rule_hdl);
if (ipa_ctx->excp_hdr_hdl)
@ -60,7 +60,7 @@ index 393d580..011500c 100644
ipa2_teardown_sys_pipe(ipa_ctx->clnt_hdl_cmd);
fail_cmd:
return result;
@@ -2767,7 +2768,7 @@ static void ipa_teardown_apps_pipes(void)
@@ -2813,7 +2814,7 @@ static void ipa_teardown_apps_pipes(void)
ipa2_teardown_sys_pipe(ipa_ctx->clnt_hdl_data_in);
__ipa_del_rt_rule(ipa_ctx->dflt_v6_rt_rule_hdl);
__ipa_del_rt_rule(ipa_ctx->dflt_v4_rt_rule_hdl);
@ -70,16 +70,16 @@ index 393d580..011500c 100644
}
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c
index 1452c59..a3caf3e 100644
index ee4ddbb..6a66b0b 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2015, 2017, The Linux Foundation. All rights reserved.
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, 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
@@ -731,7 +731,8 @@ error:
@@ -805,7 +805,8 @@ error:
return -EPERM;
}
@ -89,7 +89,7 @@ index 1452c59..a3caf3e 100644
{
struct ipa_hdr_proc_ctx_entry *entry;
struct ipa_hdr_proc_ctx_tbl *htbl = &ipa_ctx->hdr_proc_ctx_tbl;
@@ -745,6 +746,14 @@ static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr)
@@ -819,6 +820,14 @@ static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr)
IPADBG("del ctx proc cnt=%d ofst=%d\n",
htbl->proc_ctx_cnt, entry->offset_entry->offset);
@ -104,16 +104,16 @@ index 1452c59..a3caf3e 100644
if (--entry->ref_cnt) {
IPADBG("proc_ctx_hdl %x ref_cnt %d\n",
proc_ctx_hdl, entry->ref_cnt);
@@ -752,7 +761,7 @@ static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr)
@@ -826,7 +835,7 @@ static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr)
}
if (release_hdr)
- __ipa_release_hdr(entry->hdr->id);
- __ipa_del_hdr(entry->hdr->id);
+ __ipa_del_hdr(entry->hdr->id, false);
/* move the offset entry to appropriate free list */
list_move(&entry->offset_entry->link,
@@ -769,7 +778,7 @@ static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr)
@@ -843,7 +852,7 @@ static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr)
}
@ -122,7 +122,7 @@ index 1452c59..a3caf3e 100644
{
struct ipa_hdr_entry *entry;
struct ipa_hdr_tbl *htbl = &ipa_ctx->hdr_tbl;
@@ -780,7 +789,7 @@ int __ipa_del_hdr(u32 hdr_hdl)
@@ -854,7 +863,7 @@ int __ipa_del_hdr(u32 hdr_hdl)
return -EINVAL;
}
@ -131,8 +131,8 @@ index 1452c59..a3caf3e 100644
IPAERR("bad parm\n");
return -EINVAL;
}
@@ -788,6 +797,14 @@ int __ipa_del_hdr(u32 hdr_hdl)
IPADBG("del hdr of sz=%d hdr_cnt=%d ofst=%d\n", entry->hdr_len,
@@ -866,6 +875,14 @@ int __ipa_del_hdr(u32 hdr_hdl)
IPADBG("del hdr of sz=%d hdr_cnt=%d ofst=%d\n", entry->hdr_len,
htbl->hdr_cnt, entry->offset_entry->offset);
+ if (by_user && entry->user_deleted) {
@ -146,7 +146,7 @@ index 1452c59..a3caf3e 100644
if (--entry->ref_cnt) {
IPADBG("hdr_hdl %x ref_cnt %d\n", hdr_hdl, entry->ref_cnt);
return 0;
@@ -798,7 +815,7 @@ int __ipa_del_hdr(u32 hdr_hdl)
@@ -876,7 +893,7 @@ int __ipa_del_hdr(u32 hdr_hdl)
entry->phys_base,
entry->hdr_len,
DMA_TO_DEVICE);
@ -155,7 +155,7 @@ index 1452c59..a3caf3e 100644
} else {
/* move the offset entry to appropriate free list */
list_move(&entry->offset_entry->link,
@@ -865,15 +882,16 @@ bail:
@@ -943,15 +960,16 @@ bail:
}
/**
@ -175,7 +175,7 @@ index 1452c59..a3caf3e 100644
{
int i;
int result = -EFAULT;
@@ -890,7 +908,7 @@ int ipa2_del_hdr(struct ipa_ioc_del_hdr *hdls)
@@ -968,7 +986,7 @@ int ipa2_del_hdr(struct ipa_ioc_del_hdr *hdls)
mutex_lock(&ipa_ctx->lock);
for (i = 0; i < hdls->num_hdls; i++) {
@ -184,7 +184,7 @@ index 1452c59..a3caf3e 100644
IPAERR("failed to del hdr %i\n", i);
hdls->hdl[i].status = -1;
} else {
@@ -911,6 +929,20 @@ bail:
@@ -989,6 +1007,20 @@ bail:
}
/**
@ -205,7 +205,7 @@ index 1452c59..a3caf3e 100644
* ipa2_add_hdr_proc_ctx() - add the specified headers to SW
* and optionally commit them to IPA HW
* @proc_ctxs: [inout] set of processing context headers to add
@@ -962,16 +994,18 @@ bail:
@@ -1040,16 +1072,18 @@ bail:
}
/**
@ -226,7 +226,7 @@ index 1452c59..a3caf3e 100644
{
int i;
int result;
@@ -990,7 +1024,7 @@ int ipa2_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls)
@@ -1068,7 +1102,7 @@ int ipa2_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls)
mutex_lock(&ipa_ctx->lock);
for (i = 0; i < hdls->num_hdls; i++) {
@ -235,7 +235,7 @@ index 1452c59..a3caf3e 100644
IPAERR("failed to del hdr %i\n", i);
hdls->hdl[i].status = -1;
} else {
@@ -1011,6 +1045,21 @@ bail:
@@ -1089,6 +1123,21 @@ bail:
}
/**
@ -257,7 +257,7 @@ index 1452c59..a3caf3e 100644
* ipa2_commit_hdr() - commit to IPA HW the current header table in SW
*
* Returns: 0 on success, negative on failure
@@ -1231,7 +1280,7 @@ int __ipa_release_hdr(u32 hdr_hdl)
@@ -1316,7 +1365,7 @@ int __ipa_release_hdr(u32 hdr_hdl)
{
int result = 0;
@ -266,7 +266,7 @@ index 1452c59..a3caf3e 100644
IPADBG("fail to del hdr %x\n", hdr_hdl);
result = -EFAULT;
goto bail;
@@ -1259,7 +1308,7 @@ int __ipa_release_hdr_proc_ctx(u32 proc_ctx_hdl)
@@ -1344,7 +1393,7 @@ int __ipa_release_hdr_proc_ctx(u32 proc_ctx_hdl)
{
int result = 0;
@ -276,7 +276,7 @@ index 1452c59..a3caf3e 100644
result = -EFAULT;
goto bail;
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
index b3827ab..13892ce 100644
index 67d8c94..9094f19 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
@@ -1,4 +1,4 @@
@ -285,7 +285,7 @@ index b3827ab..13892ce 100644
*
* 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
@@ -367,6 +367,7 @@ struct ipa_rt_tbl {
@@ -254,6 +254,7 @@ struct ipa_rt_tbl {
* @id: header entry id
* @is_eth2_ofst_valid: is eth2_ofst field valid?
* @eth2_ofst: offset to start of Ethernet-II/802.3 header
@ -293,7 +293,7 @@ index b3827ab..13892ce 100644
*/
struct ipa_hdr_entry {
struct list_head link;
@@ -384,6 +385,7 @@ struct ipa_hdr_entry {
@@ -271,6 +272,7 @@ struct ipa_hdr_entry {
int id;
u8 is_eth2_ofst_valid;
u16 eth2_ofst;
@ -301,7 +301,7 @@ index b3827ab..13892ce 100644
};
/**
@@ -459,6 +461,7 @@ struct ipa_hdr_proc_ctx_add_hdr_cmd_seq {
@@ -334,6 +336,7 @@ struct ipa_hdr_proc_ctx_add_hdr_cmd_seq {
* @cookie: cookie used for validity check
* @ref_cnt: reference counter of routing table
* @id: processing context header entry id
@ -309,7 +309,7 @@ index b3827ab..13892ce 100644
*/
struct ipa_hdr_proc_ctx_entry {
struct list_head link;
@@ -468,6 +471,7 @@ struct ipa_hdr_proc_ctx_entry {
@@ -343,6 +346,7 @@ struct ipa_hdr_proc_ctx_entry {
u32 cookie;
u32 ref_cnt;
int id;
@ -317,7 +317,7 @@ index b3827ab..13892ce 100644
};
/**
@@ -1634,6 +1638,8 @@ int ipa2_add_hdr(struct ipa_ioc_add_hdr *hdrs);
@@ -1361,6 +1365,8 @@ int ipa2_add_hdr(struct ipa_ioc_add_hdr *hdrs);
int ipa2_del_hdr(struct ipa_ioc_del_hdr *hdls);
@ -326,7 +326,7 @@ index b3827ab..13892ce 100644
int ipa2_commit_hdr(void);
int ipa2_reset_hdr(void);
@@ -1651,6 +1657,9 @@ int ipa2_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs);
@@ -1378,6 +1384,9 @@ int ipa2_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs);
int ipa2_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls);
@ -336,7 +336,7 @@ index b3827ab..13892ce 100644
/*
* Routing
*/
@@ -1979,7 +1988,7 @@ int ipa2_active_clients_log_print_table(char *buf, int size);
@@ -1669,7 +1678,7 @@ int ipa2_active_clients_log_print_table(char *buf, int size);
void ipa2_active_clients_log_clear(void);
int ipa_interrupts_init(u32 ipa_irq, u32 ee, struct device *ipa_dev);
int __ipa_del_rt_rule(u32 rule_hdl);
@ -346,10 +346,10 @@ index b3827ab..13892ce 100644
int __ipa_release_hdr_proc_ctx(u32 proc_ctx_hdl);
int _ipa_read_gen_reg_v1_1(char *buff, int max_len);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index 96089b1..56e7ab8 100644
index e87c4e2..aa83cbd 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -794,7 +794,8 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
@@ -784,7 +784,8 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
retval = -EINVAL;
break;
}
@ -359,7 +359,7 @@ index 96089b1..56e7ab8 100644
retval = -EFAULT;
break;
}
@@ -1563,8 +1564,8 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
@@ -1553,8 +1554,8 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
retval = -EINVAL;
break;
}
@ -370,7 +370,7 @@ index 96089b1..56e7ab8 100644
retval = -EFAULT;
break;
}
@@ -3038,7 +3039,7 @@ fail_schedule_delayed_work:
@@ -3003,7 +3004,7 @@ fail_schedule_delayed_work:
if (ipa3_ctx->dflt_v4_rt_rule_hdl)
__ipa3_del_rt_rule(ipa3_ctx->dflt_v4_rt_rule_hdl);
if (ipa3_ctx->excp_hdr_hdl)
@ -379,7 +379,7 @@ index 96089b1..56e7ab8 100644
ipa3_teardown_sys_pipe(ipa3_ctx->clnt_hdl_cmd);
fail_cmd:
return result;
@@ -3050,7 +3051,7 @@ static void ipa3_teardown_apps_pipes(void)
@@ -3015,7 +3016,7 @@ static void ipa3_teardown_apps_pipes(void)
ipa3_teardown_sys_pipe(ipa3_ctx->clnt_hdl_data_in);
__ipa3_del_rt_rule(ipa3_ctx->dflt_v6_rt_rule_hdl);
__ipa3_del_rt_rule(ipa3_ctx->dflt_v4_rt_rule_hdl);
@ -389,7 +389,7 @@ index 96089b1..56e7ab8 100644
}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
index b8baa53..523c1df 100644
index c7202be..1c3af6e 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
@@ -1,4 +1,4 @@
@ -398,7 +398,7 @@ index b8baa53..523c1df 100644
*
* 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
@@ -603,7 +603,8 @@ error:
@@ -573,7 +573,8 @@ error:
return -EPERM;
}
@ -408,8 +408,8 @@ index b8baa53..523c1df 100644
{
struct ipa3_hdr_proc_ctx_entry *entry;
struct ipa3_hdr_proc_ctx_tbl *htbl = &ipa3_ctx->hdr_proc_ctx_tbl;
@@ -617,6 +618,14 @@ static int __ipa3_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr)
IPADBG("del ctx proc cnt=%d ofst=%d\n",
@@ -587,6 +588,14 @@ static int __ipa3_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr)
IPADBG("del proc ctx cnt=%d ofst=%d\n",
htbl->proc_ctx_cnt, entry->offset_entry->offset);
+ if (by_user && entry->user_deleted) {
@ -423,16 +423,16 @@ index b8baa53..523c1df 100644
if (--entry->ref_cnt) {
IPADBG("proc_ctx_hdl %x ref_cnt %d\n",
proc_ctx_hdl, entry->ref_cnt);
@@ -624,7 +633,7 @@ static int __ipa3_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr)
@@ -594,7 +603,7 @@ static int __ipa3_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr)
}
if (release_hdr)
- __ipa3_release_hdr(entry->hdr->id);
- __ipa3_del_hdr(entry->hdr->id);
+ __ipa3_del_hdr(entry->hdr->id, false);
/* move the offset entry to appropriate free list */
list_move(&entry->offset_entry->link,
@@ -641,7 +650,7 @@ static int __ipa3_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr)
@@ -611,7 +620,7 @@ static int __ipa3_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr)
}
@ -441,7 +441,7 @@ index b8baa53..523c1df 100644
{
struct ipa3_hdr_entry *entry;
struct ipa3_hdr_tbl *htbl = &ipa3_ctx->hdr_tbl;
@@ -652,7 +661,7 @@ int __ipa3_del_hdr(u32 hdr_hdl)
@@ -622,7 +631,7 @@ int __ipa3_del_hdr(u32 hdr_hdl)
return -EINVAL;
}
@ -450,9 +450,9 @@ index b8baa53..523c1df 100644
IPAERR("bad parm\n");
return -EINVAL;
}
@@ -660,6 +669,14 @@ int __ipa3_del_hdr(u32 hdr_hdl)
IPADBG("del hdr of sz=%d hdr_cnt=%d ofst=%d\n", entry->hdr_len,
htbl->hdr_cnt, entry->offset_entry->offset);
@@ -635,6 +644,14 @@ int __ipa3_del_hdr(u32 hdr_hdl)
entry->hdr_len, htbl->hdr_cnt,
entry->offset_entry->offset);
+ if (by_user && entry->user_deleted) {
+ IPAERR("proc_ctx already deleted by user\n");
@ -465,7 +465,7 @@ index b8baa53..523c1df 100644
if (--entry->ref_cnt) {
IPADBG("hdr_hdl %x ref_cnt %d\n", hdr_hdl, entry->ref_cnt);
return 0;
@@ -670,7 +687,7 @@ int __ipa3_del_hdr(u32 hdr_hdl)
@@ -645,7 +662,7 @@ int __ipa3_del_hdr(u32 hdr_hdl)
entry->phys_base,
entry->hdr_len,
DMA_TO_DEVICE);
@ -474,7 +474,7 @@ index b8baa53..523c1df 100644
} else {
/* move the offset entry to appropriate free list */
list_move(&entry->offset_entry->link,
@@ -732,15 +749,16 @@ bail:
@@ -707,15 +724,16 @@ bail:
}
/**
@ -494,7 +494,7 @@ index b8baa53..523c1df 100644
{
int i;
int result = -EFAULT;
@@ -752,7 +770,7 @@ int ipa3_del_hdr(struct ipa_ioc_del_hdr *hdls)
@@ -727,7 +745,7 @@ int ipa3_del_hdr(struct ipa_ioc_del_hdr *hdls)
mutex_lock(&ipa3_ctx->lock);
for (i = 0; i < hdls->num_hdls; i++) {
@ -503,7 +503,7 @@ index b8baa53..523c1df 100644
IPAERR("failed to del hdr %i\n", i);
hdls->hdl[i].status = -1;
} else {
@@ -773,6 +791,20 @@ bail:
@@ -748,6 +766,20 @@ bail:
}
/**
@ -524,7 +524,7 @@ index b8baa53..523c1df 100644
* ipa3_add_hdr_proc_ctx() - add the specified headers to SW
* and optionally commit them to IPA HW
* @proc_ctxs: [inout] set of processing context headers to add
@@ -817,16 +849,18 @@ bail:
@@ -792,16 +824,18 @@ bail:
}
/**
@ -545,7 +545,7 @@ index b8baa53..523c1df 100644
{
int i;
int result;
@@ -838,7 +872,7 @@ int ipa3_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls)
@@ -813,7 +847,7 @@ int ipa3_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls)
mutex_lock(&ipa3_ctx->lock);
for (i = 0; i < hdls->num_hdls; i++) {
@ -554,7 +554,7 @@ index b8baa53..523c1df 100644
IPAERR("failed to del hdr %i\n", i);
hdls->hdl[i].status = -1;
} else {
@@ -859,6 +893,21 @@ bail:
@@ -834,6 +868,21 @@ bail:
}
/**
@ -576,7 +576,7 @@ index b8baa53..523c1df 100644
* ipa3_commit_hdr() - commit to IPA HW the current header table in SW
*
* Returns: 0 on success, negative on failure
@@ -1079,7 +1128,7 @@ int __ipa3_release_hdr(u32 hdr_hdl)
@@ -1061,7 +1110,7 @@ int __ipa3_release_hdr(u32 hdr_hdl)
{
int result = 0;
@ -585,7 +585,7 @@ index b8baa53..523c1df 100644
IPADBG("fail to del hdr %x\n", hdr_hdl);
result = -EFAULT;
goto bail;
@@ -1107,7 +1156,7 @@ int __ipa3_release_hdr_proc_ctx(u32 proc_ctx_hdl)
@@ -1089,7 +1138,7 @@ int __ipa3_release_hdr_proc_ctx(u32 proc_ctx_hdl)
{
int result = 0;
@ -595,10 +595,10 @@ index b8baa53..523c1df 100644
result = -EFAULT;
goto bail;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
index b4a9ac3..b2e6b90 100644
index a6c74973..3f19c21 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -430,6 +430,7 @@ struct ipa3_rt_tbl {
@@ -316,6 +316,7 @@ struct ipa3_rt_tbl {
* @id: header entry id
* @is_eth2_ofst_valid: is eth2_ofst field valid?
* @eth2_ofst: offset to start of Ethernet-II/802.3 header
@ -606,7 +606,7 @@ index b4a9ac3..b2e6b90 100644
*/
struct ipa3_hdr_entry {
struct list_head link;
@@ -447,6 +448,7 @@ struct ipa3_hdr_entry {
@@ -333,6 +334,7 @@ struct ipa3_hdr_entry {
int id;
u8 is_eth2_ofst_valid;
u16 eth2_ofst;
@ -614,7 +614,7 @@ index b4a9ac3..b2e6b90 100644
};
/**
@@ -522,6 +524,7 @@ struct ipa3_hdr_proc_ctx_add_hdr_cmd_seq {
@@ -372,6 +374,7 @@ struct ipa3_hdr_proc_ctx_offset_entry {
* @cookie: cookie used for validity check
* @ref_cnt: reference counter of routing table
* @id: processing context header entry id
@ -622,7 +622,7 @@ index b4a9ac3..b2e6b90 100644
*/
struct ipa3_hdr_proc_ctx_entry {
struct list_head link;
@@ -531,6 +534,7 @@ struct ipa3_hdr_proc_ctx_entry {
@@ -381,6 +384,7 @@ struct ipa3_hdr_proc_ctx_entry {
u32 cookie;
u32 ref_cnt;
int id;
@ -630,7 +630,7 @@ index b4a9ac3..b2e6b90 100644
};
/**
@@ -1816,6 +1820,8 @@ int ipa3_add_hdr(struct ipa_ioc_add_hdr *hdrs);
@@ -1520,6 +1524,8 @@ int ipa3_add_hdr(struct ipa_ioc_add_hdr *hdrs);
int ipa3_del_hdr(struct ipa_ioc_del_hdr *hdls);
@ -639,7 +639,7 @@ index b4a9ac3..b2e6b90 100644
int ipa3_commit_hdr(void);
int ipa3_reset_hdr(void);
@@ -1833,6 +1839,9 @@ int ipa3_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs);
@@ -1537,6 +1543,9 @@ int ipa3_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs);
int ipa3_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls);
@ -649,7 +649,7 @@ index b4a9ac3..b2e6b90 100644
/*
* Routing
*/
@@ -2175,7 +2184,7 @@ int ipa3_active_clients_log_print_table(char *buf, int size);
@@ -1842,7 +1851,7 @@ int ipa3_active_clients_log_print_table(char *buf, int size);
void ipa3_active_clients_log_clear(void);
int ipa3_interrupts_init(u32 ipa_irq, u32 ee, struct device *ipa_dev);
int __ipa3_del_rt_rule(u32 rule_hdl);

View file

@ -0,0 +1,669 @@
From 7452cc75cbd363107a1e5d4c5f1327d3edc797ef Mon Sep 17 00:00:00 2001
From: Ghanim Fodi <gfodi@codeaurora.org>
Date: Thu, 12 Jan 2017 15:14:15 +0200
Subject: msm: ipa: Prevent multiple header deletion from user space
An IPA header or processing context can be added once
and later deleted once from user space.
Multiple deletion may cause invalid state of the headers
software cache.
Change-Id: Ic0b8472b7fd8a76233a007d90c832af726184574
CRs-fixed: 1097714
Signed-off-by: Ghanim Fodi <gfodi@codeaurora.org>
---
drivers/platform/msm/ipa/ipa_v2/ipa.c | 13 ++---
drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c | 79 +++++++++++++++++++++++++------
drivers/platform/msm/ipa/ipa_v2/ipa_i.h | 11 ++++-
drivers/platform/msm/ipa/ipa_v3/ipa.c | 13 ++---
drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c | 79 +++++++++++++++++++++++++------
drivers/platform/msm/ipa/ipa_v3/ipa_i.h | 13 ++++-
6 files changed, 163 insertions(+), 45 deletions(-)
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa.c b/drivers/platform/msm/ipa/ipa_v2/ipa.c
index d82651f..09ec845 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, 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
@@ -733,7 +733,8 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
retval = -EFAULT;
break;
}
- if (ipa2_del_hdr((struct ipa_ioc_del_hdr *)param)) {
+ if (ipa2_del_hdr_by_user((struct ipa_ioc_del_hdr *)param,
+ true)) {
retval = -EFAULT;
break;
}
@@ -1417,8 +1418,8 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
retval = -EFAULT;
break;
}
- if (ipa2_del_hdr_proc_ctx(
- (struct ipa_ioc_del_hdr_proc_ctx *)param)) {
+ if (ipa2_del_hdr_proc_ctx_by_user(
+ (struct ipa_ioc_del_hdr_proc_ctx *)param, true)) {
retval = -EFAULT;
break;
}
@@ -2715,7 +2716,7 @@ fail_schedule_delayed_work:
if (ipa_ctx->dflt_v4_rt_rule_hdl)
__ipa_del_rt_rule(ipa_ctx->dflt_v4_rt_rule_hdl);
if (ipa_ctx->excp_hdr_hdl)
- __ipa_del_hdr(ipa_ctx->excp_hdr_hdl);
+ __ipa_del_hdr(ipa_ctx->excp_hdr_hdl, false);
ipa2_teardown_sys_pipe(ipa_ctx->clnt_hdl_cmd);
fail_cmd:
return result;
@@ -2727,7 +2728,7 @@ static void ipa_teardown_apps_pipes(void)
ipa2_teardown_sys_pipe(ipa_ctx->clnt_hdl_data_in);
__ipa_del_rt_rule(ipa_ctx->dflt_v6_rt_rule_hdl);
__ipa_del_rt_rule(ipa_ctx->dflt_v4_rt_rule_hdl);
- __ipa_del_hdr(ipa_ctx->excp_hdr_hdl);
+ __ipa_del_hdr(ipa_ctx->excp_hdr_hdl, false);
ipa2_teardown_sys_pipe(ipa_ctx->clnt_hdl_cmd);
}
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c
index 40d42e17..51f34f0 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, 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
@@ -741,7 +741,8 @@ error:
return -EPERM;
}
-static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr)
+static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl,
+ bool release_hdr, bool by_user)
{
struct ipa_hdr_proc_ctx_entry *entry;
struct ipa_hdr_proc_ctx_tbl *htbl = &ipa_ctx->hdr_proc_ctx_tbl;
@@ -755,6 +756,14 @@ static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr)
IPADBG("del ctx proc cnt=%d ofst=%d\n",
htbl->proc_ctx_cnt, entry->offset_entry->offset);
+ if (by_user && entry->user_deleted) {
+ IPAERR("proc_ctx already deleted by user\n");
+ return -EINVAL;
+ }
+
+ if (by_user)
+ entry->user_deleted = true;
+
if (--entry->ref_cnt) {
IPADBG("proc_ctx_hdl %x ref_cnt %d\n",
proc_ctx_hdl, entry->ref_cnt);
@@ -762,7 +771,7 @@ static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr)
}
if (release_hdr)
- __ipa_del_hdr(entry->hdr->id);
+ __ipa_del_hdr(entry->hdr->id, false);
/* move the offset entry to appropriate free list */
list_move(&entry->offset_entry->link,
@@ -779,7 +788,7 @@ static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr)
}
-int __ipa_del_hdr(u32 hdr_hdl)
+int __ipa_del_hdr(u32 hdr_hdl, bool by_user)
{
struct ipa_hdr_entry *entry;
struct ipa_hdr_tbl *htbl = &ipa_ctx->hdr_tbl;
@@ -790,7 +799,7 @@ int __ipa_del_hdr(u32 hdr_hdl)
return -EINVAL;
}
- if (!entry || (entry->cookie != IPA_COOKIE)) {
+ if (entry->cookie != IPA_COOKIE) {
IPAERR("bad parm\n");
return -EINVAL;
}
@@ -802,6 +811,14 @@ int __ipa_del_hdr(u32 hdr_hdl)
IPADBG("del hdr of sz=%d hdr_cnt=%d ofst=%d\n", entry->hdr_len,
htbl->hdr_cnt, entry->offset_entry->offset);
+ if (by_user && entry->user_deleted) {
+ IPAERR("hdr already deleted by user\n");
+ return -EINVAL;
+ }
+
+ if (by_user)
+ entry->user_deleted = true;
+
if (--entry->ref_cnt) {
IPADBG("hdr_hdl %x ref_cnt %d\n", hdr_hdl, entry->ref_cnt);
return 0;
@@ -812,7 +829,7 @@ int __ipa_del_hdr(u32 hdr_hdl)
entry->phys_base,
entry->hdr_len,
DMA_TO_DEVICE);
- __ipa_del_hdr_proc_ctx(entry->proc_ctx->id, false);
+ __ipa_del_hdr_proc_ctx(entry->proc_ctx->id, false, false);
} else {
/* move the offset entry to appropriate free list */
list_move(&entry->offset_entry->link,
@@ -879,15 +896,16 @@ bail:
}
/**
- * ipa2_del_hdr() - Remove the specified headers from SW and optionally commit them
- * to IPA HW
+ * ipa2_del_hdr_by_user() - Remove the specified headers
+ * from SW and optionally commit them to IPA HW
* @hdls: [inout] set of headers to delete
+ * @by_user: Operation requested by user?
*
* Returns: 0 on success, negative on failure
*
* Note: Should not be called from atomic context
*/
-int ipa2_del_hdr(struct ipa_ioc_del_hdr *hdls)
+int ipa2_del_hdr_by_user(struct ipa_ioc_del_hdr *hdls, bool by_user)
{
int i;
int result = -EFAULT;
@@ -904,7 +922,7 @@ int ipa2_del_hdr(struct ipa_ioc_del_hdr *hdls)
mutex_lock(&ipa_ctx->lock);
for (i = 0; i < hdls->num_hdls; i++) {
- if (__ipa_del_hdr(hdls->hdl[i].hdl)) {
+ if (__ipa_del_hdr(hdls->hdl[i].hdl, by_user)) {
IPAERR("failed to del hdr %i\n", i);
hdls->hdl[i].status = -1;
} else {
@@ -925,6 +943,20 @@ bail:
}
/**
+ * ipa2_del_hdr() - Remove the specified headers from SW
+ * and optionally commit them to IPA HW
+ * @hdls: [inout] set of headers to delete
+ *
+ * Returns: 0 on success, negative on failure
+ *
+ * Note: Should not be called from atomic context
+ */
+int ipa2_del_hdr(struct ipa_ioc_del_hdr *hdls)
+{
+ return ipa2_del_hdr_by_user(hdls, false);
+}
+
+/**
* ipa2_add_hdr_proc_ctx() - add the specified headers to SW
* and optionally commit them to IPA HW
* @proc_ctxs: [inout] set of processing context headers to add
@@ -976,16 +1008,18 @@ bail:
}
/**
- * ipa2_del_hdr_proc_ctx() -
+ * ipa2_del_hdr_proc_ctx_by_user() -
* Remove the specified processing context headers from SW and
* optionally commit them to IPA HW.
* @hdls: [inout] set of processing context headers to delete
+ * @by_user: Operation requested by user?
*
* Returns: 0 on success, negative on failure
*
* Note: Should not be called from atomic context
*/
-int ipa2_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls)
+int ipa2_del_hdr_proc_ctx_by_user(struct ipa_ioc_del_hdr_proc_ctx *hdls,
+ bool by_user)
{
int i;
int result;
@@ -1004,7 +1038,7 @@ int ipa2_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls)
mutex_lock(&ipa_ctx->lock);
for (i = 0; i < hdls->num_hdls; i++) {
- if (__ipa_del_hdr_proc_ctx(hdls->hdl[i].hdl, true)) {
+ if (__ipa_del_hdr_proc_ctx(hdls->hdl[i].hdl, true, by_user)) {
IPAERR("failed to del hdr %i\n", i);
hdls->hdl[i].status = -1;
} else {
@@ -1025,6 +1059,21 @@ bail:
}
/**
+ * ipa2_del_hdr_proc_ctx() -
+ * Remove the specified processing context headers from SW and
+ * optionally commit them to IPA HW.
+ * @hdls: [inout] set of processing context headers to delete
+ *
+ * Returns: 0 on success, negative on failure
+ *
+ * Note: Should not be called from atomic context
+ */
+int ipa2_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls)
+{
+ return ipa2_del_hdr_proc_ctx_by_user(hdls, false);
+}
+
+/**
* ipa2_commit_hdr() - commit to IPA HW the current header table in SW
*
* Returns: 0 on success, negative on failure
@@ -1252,7 +1301,7 @@ int __ipa_release_hdr(u32 hdr_hdl)
{
int result = 0;
- if (__ipa_del_hdr(hdr_hdl)) {
+ if (__ipa_del_hdr(hdr_hdl, false)) {
IPADBG("fail to del hdr %x\n", hdr_hdl);
result = -EFAULT;
goto bail;
@@ -1280,7 +1329,7 @@ int __ipa_release_hdr_proc_ctx(u32 proc_ctx_hdl)
{
int result = 0;
- if (__ipa_del_hdr_proc_ctx(proc_ctx_hdl, true)) {
+ if (__ipa_del_hdr_proc_ctx(proc_ctx_hdl, true, false)) {
IPADBG("fail to del hdr %x\n", proc_ctx_hdl);
result = -EFAULT;
goto bail;
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
index 967036a..2c2a9c6 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
@@ -281,6 +281,7 @@ struct ipa_rt_tbl {
* @id: header entry id
* @is_eth2_ofst_valid: is eth2_ofst field valid?
* @eth2_ofst: offset to start of Ethernet-II/802.3 header
+ * @user_deleted: is the header deleted by the user?
*/
struct ipa_hdr_entry {
struct list_head link;
@@ -298,6 +299,7 @@ struct ipa_hdr_entry {
int id;
u8 is_eth2_ofst_valid;
u16 eth2_ofst;
+ bool user_deleted;
};
/**
@@ -361,6 +363,7 @@ struct ipa_hdr_proc_ctx_add_hdr_cmd_seq {
* @cookie: cookie used for validity check
* @ref_cnt: reference counter of routing table
* @id: processing context header entry id
+ * @user_deleted: is the hdr processing context deleted by the user?
*/
struct ipa_hdr_proc_ctx_entry {
struct list_head link;
@@ -370,6 +373,7 @@ struct ipa_hdr_proc_ctx_entry {
u32 cookie;
u32 ref_cnt;
int id;
+ bool user_deleted;
};
/**
@@ -1400,6 +1404,8 @@ int ipa2_add_hdr(struct ipa_ioc_add_hdr *hdrs);
int ipa2_del_hdr(struct ipa_ioc_del_hdr *hdls);
+int ipa2_del_hdr_by_user(struct ipa_ioc_del_hdr *hdls, bool by_user);
+
int ipa2_commit_hdr(void);
int ipa2_reset_hdr(void);
@@ -1417,6 +1423,9 @@ int ipa2_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs);
int ipa2_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls);
+int ipa2_del_hdr_proc_ctx_by_user(struct ipa_ioc_del_hdr_proc_ctx *hdls,
+ bool by_user);
+
/*
* Routing
*/
@@ -1709,7 +1718,7 @@ int ipa2_active_clients_log_print_table(char *buf, int size);
void ipa2_active_clients_log_clear(void);
int ipa_interrupts_init(u32 ipa_irq, u32 ee, struct device *ipa_dev);
int __ipa_del_rt_rule(u32 rule_hdl);
-int __ipa_del_hdr(u32 hdr_hdl);
+int __ipa_del_hdr(u32 hdr_hdl, bool by_user);
int __ipa_release_hdr(u32 hdr_hdl);
int __ipa_release_hdr_proc_ctx(u32 proc_ctx_hdl);
int _ipa_read_gen_reg_v1_1(char *buff, int max_len);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index 3d276b0..2da3b0d 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, 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
@@ -784,7 +784,8 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
retval = -EFAULT;
break;
}
- if (ipa3_del_hdr((struct ipa_ioc_del_hdr *)param)) {
+ if (ipa3_del_hdr_by_user((struct ipa_ioc_del_hdr *)param,
+ true)) {
retval = -EFAULT;
break;
}
@@ -1553,8 +1554,8 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
retval = -EFAULT;
break;
}
- if (ipa3_del_hdr_proc_ctx(
- (struct ipa_ioc_del_hdr_proc_ctx *)param)) {
+ if (ipa3_del_hdr_proc_ctx_by_user(
+ (struct ipa_ioc_del_hdr_proc_ctx *)param, true)) {
retval = -EFAULT;
break;
}
@@ -2921,7 +2922,7 @@ fail_schedule_delayed_work:
if (ipa3_ctx->dflt_v4_rt_rule_hdl)
__ipa3_del_rt_rule(ipa3_ctx->dflt_v4_rt_rule_hdl);
if (ipa3_ctx->excp_hdr_hdl)
- __ipa3_del_hdr(ipa3_ctx->excp_hdr_hdl);
+ __ipa3_del_hdr(ipa3_ctx->excp_hdr_hdl, false);
ipa3_teardown_sys_pipe(ipa3_ctx->clnt_hdl_cmd);
fail_cmd:
return result;
@@ -2933,7 +2934,7 @@ static void ipa3_teardown_apps_pipes(void)
ipa3_teardown_sys_pipe(ipa3_ctx->clnt_hdl_data_in);
__ipa3_del_rt_rule(ipa3_ctx->dflt_v6_rt_rule_hdl);
__ipa3_del_rt_rule(ipa3_ctx->dflt_v4_rt_rule_hdl);
- __ipa3_del_hdr(ipa3_ctx->excp_hdr_hdl);
+ __ipa3_del_hdr(ipa3_ctx->excp_hdr_hdl, false);
ipa3_teardown_sys_pipe(ipa3_ctx->clnt_hdl_cmd);
}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
index 93fa149..69dca76 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, 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
@@ -576,7 +576,8 @@ error:
return -EPERM;
}
-static int __ipa3_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr)
+static int __ipa3_del_hdr_proc_ctx(u32 proc_ctx_hdl,
+ bool release_hdr, bool by_user)
{
struct ipa3_hdr_proc_ctx_entry *entry;
struct ipa3_hdr_proc_ctx_tbl *htbl = &ipa3_ctx->hdr_proc_ctx_tbl;
@@ -590,6 +591,14 @@ static int __ipa3_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr)
IPADBG("del proc ctx cnt=%d ofst=%d\n",
htbl->proc_ctx_cnt, entry->offset_entry->offset);
+ if (by_user && entry->user_deleted) {
+ IPAERR("proc_ctx already deleted by user\n");
+ return -EINVAL;
+ }
+
+ if (by_user)
+ entry->user_deleted = true;
+
if (--entry->ref_cnt) {
IPADBG("proc_ctx_hdl %x ref_cnt %d\n",
proc_ctx_hdl, entry->ref_cnt);
@@ -597,7 +606,7 @@ static int __ipa3_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr)
}
if (release_hdr)
- __ipa3_del_hdr(entry->hdr->id);
+ __ipa3_del_hdr(entry->hdr->id, false);
/* move the offset entry to appropriate free list */
list_move(&entry->offset_entry->link,
@@ -614,7 +623,7 @@ static int __ipa3_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr)
}
-int __ipa3_del_hdr(u32 hdr_hdl)
+int __ipa3_del_hdr(u32 hdr_hdl, bool by_user)
{
struct ipa3_hdr_entry *entry;
struct ipa3_hdr_tbl *htbl = &ipa3_ctx->hdr_tbl;
@@ -625,7 +634,7 @@ int __ipa3_del_hdr(u32 hdr_hdl)
return -EINVAL;
}
- if (!entry || (entry->cookie != IPA_COOKIE)) {
+ if (entry->cookie != IPA_COOKIE) {
IPAERR("bad parm\n");
return -EINVAL;
}
@@ -638,6 +647,14 @@ int __ipa3_del_hdr(u32 hdr_hdl)
entry->hdr_len, htbl->hdr_cnt,
entry->offset_entry->offset);
+ if (by_user && entry->user_deleted) {
+ IPAERR("proc_ctx already deleted by user\n");
+ return -EINVAL;
+ }
+
+ if (by_user)
+ entry->user_deleted = true;
+
if (--entry->ref_cnt) {
IPADBG("hdr_hdl %x ref_cnt %d\n", hdr_hdl, entry->ref_cnt);
return 0;
@@ -648,7 +665,7 @@ int __ipa3_del_hdr(u32 hdr_hdl)
entry->phys_base,
entry->hdr_len,
DMA_TO_DEVICE);
- __ipa3_del_hdr_proc_ctx(entry->proc_ctx->id, false);
+ __ipa3_del_hdr_proc_ctx(entry->proc_ctx->id, false, false);
} else {
/* move the offset entry to appropriate free list */
list_move(&entry->offset_entry->link,
@@ -710,15 +727,16 @@ bail:
}
/**
- * ipa3_del_hdr() - Remove the specified headers from SW and optionally commit them
- * to IPA HW
+ * ipa3_del_hdr_by_user() - Remove the specified headers
+ * from SW and optionally commit them to IPA HW
* @hdls: [inout] set of headers to delete
+ * @by_user: Operation requested by user?
*
* Returns: 0 on success, negative on failure
*
* Note: Should not be called from atomic context
*/
-int ipa3_del_hdr(struct ipa_ioc_del_hdr *hdls)
+int ipa3_del_hdr_by_user(struct ipa_ioc_del_hdr *hdls, bool by_user)
{
int i;
int result = -EFAULT;
@@ -730,7 +748,7 @@ int ipa3_del_hdr(struct ipa_ioc_del_hdr *hdls)
mutex_lock(&ipa3_ctx->lock);
for (i = 0; i < hdls->num_hdls; i++) {
- if (__ipa3_del_hdr(hdls->hdl[i].hdl)) {
+ if (__ipa3_del_hdr(hdls->hdl[i].hdl, by_user)) {
IPAERR("failed to del hdr %i\n", i);
hdls->hdl[i].status = -1;
} else {
@@ -751,6 +769,20 @@ bail:
}
/**
+ * ipa3_del_hdr() - Remove the specified headers from SW
+ * and optionally commit them to IPA HW
+ * @hdls: [inout] set of headers to delete
+ *
+ * Returns: 0 on success, negative on failure
+ *
+ * Note: Should not be called from atomic context
+ */
+int ipa3_del_hdr(struct ipa_ioc_del_hdr *hdls)
+{
+ return ipa3_del_hdr_by_user(hdls, false);
+}
+
+/**
* ipa3_add_hdr_proc_ctx() - add the specified headers to SW
* and optionally commit them to IPA HW
* @proc_ctxs: [inout] set of processing context headers to add
@@ -795,16 +827,18 @@ bail:
}
/**
- * ipa3_del_hdr_proc_ctx() -
+ * ipa3_del_hdr_proc_ctx_by_user() -
* Remove the specified processing context headers from SW and
* optionally commit them to IPA HW.
* @hdls: [inout] set of processing context headers to delete
+ * @by_user: Operation requested by user?
*
* Returns: 0 on success, negative on failure
*
* Note: Should not be called from atomic context
*/
-int ipa3_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls)
+int ipa3_del_hdr_proc_ctx_by_user(struct ipa_ioc_del_hdr_proc_ctx *hdls,
+ bool by_user)
{
int i;
int result;
@@ -816,7 +850,7 @@ int ipa3_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls)
mutex_lock(&ipa3_ctx->lock);
for (i = 0; i < hdls->num_hdls; i++) {
- if (__ipa3_del_hdr_proc_ctx(hdls->hdl[i].hdl, true)) {
+ if (__ipa3_del_hdr_proc_ctx(hdls->hdl[i].hdl, true, by_user)) {
IPAERR("failed to del hdr %i\n", i);
hdls->hdl[i].status = -1;
} else {
@@ -837,6 +871,21 @@ bail:
}
/**
+ * ipa3_del_hdr_proc_ctx() -
+ * Remove the specified processing context headers from SW and
+ * optionally commit them to IPA HW.
+ * @hdls: [inout] set of processing context headers to delete
+ *
+ * Returns: 0 on success, negative on failure
+ *
+ * Note: Should not be called from atomic context
+ */
+int ipa3_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls)
+{
+ return ipa3_del_hdr_proc_ctx_by_user(hdls, false);
+}
+
+/**
* ipa3_commit_hdr() - commit to IPA HW the current header table in SW
*
* Returns: 0 on success, negative on failure
@@ -1064,7 +1113,7 @@ int __ipa3_release_hdr(u32 hdr_hdl)
{
int result = 0;
- if (__ipa3_del_hdr(hdr_hdl)) {
+ if (__ipa3_del_hdr(hdr_hdl, false)) {
IPADBG("fail to del hdr %x\n", hdr_hdl);
result = -EFAULT;
goto bail;
@@ -1092,7 +1141,7 @@ int __ipa3_release_hdr_proc_ctx(u32 proc_ctx_hdl)
{
int result = 0;
- if (__ipa3_del_hdr_proc_ctx(proc_ctx_hdl, true)) {
+ if (__ipa3_del_hdr_proc_ctx(proc_ctx_hdl, true, false)) {
IPADBG("fail to del hdr %x\n", proc_ctx_hdl);
result = -EFAULT;
goto bail;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
index fe7c88a..b3ce524 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, 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
@@ -279,6 +279,7 @@ struct ipa3_rt_tbl {
* @id: header entry id
* @is_eth2_ofst_valid: is eth2_ofst field valid?
* @eth2_ofst: offset to start of Ethernet-II/802.3 header
+ * @user_deleted: is the header deleted by the user?
*/
struct ipa3_hdr_entry {
struct list_head link;
@@ -296,6 +297,7 @@ struct ipa3_hdr_entry {
int id;
u8 is_eth2_ofst_valid;
u16 eth2_ofst;
+ bool user_deleted;
};
/**
@@ -335,6 +337,7 @@ struct ipa3_hdr_proc_ctx_offset_entry {
* @cookie: cookie used for validity check
* @ref_cnt: reference counter of routing table
* @id: processing context header entry id
+ * @user_deleted: is the hdr processing context deleted by the user?
*/
struct ipa3_hdr_proc_ctx_entry {
struct list_head link;
@@ -344,6 +347,7 @@ struct ipa3_hdr_proc_ctx_entry {
u32 cookie;
u32 ref_cnt;
int id;
+ bool user_deleted;
};
/**
@@ -1548,6 +1552,8 @@ int ipa3_add_hdr(struct ipa_ioc_add_hdr *hdrs);
int ipa3_del_hdr(struct ipa_ioc_del_hdr *hdls);
+int ipa3_del_hdr_by_user(struct ipa_ioc_del_hdr *hdls, bool by_user);
+
int ipa3_commit_hdr(void);
int ipa3_reset_hdr(void);
@@ -1565,6 +1571,9 @@ int ipa3_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs);
int ipa3_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls);
+int ipa3_del_hdr_proc_ctx_by_user(struct ipa_ioc_del_hdr_proc_ctx *hdls,
+ bool by_user);
+
/*
* Routing
*/
@@ -1869,7 +1878,7 @@ int ipa3_active_clients_log_print_table(char *buf, int size);
void ipa3_active_clients_log_clear(void);
int ipa3_interrupts_init(u32 ipa_irq, u32 ee, struct device *ipa_dev);
int __ipa3_del_rt_rule(u32 rule_hdl);
-int __ipa3_del_hdr(u32 hdr_hdl);
+int __ipa3_del_hdr(u32 hdr_hdl, bool by_user);
int __ipa3_release_hdr(u32 hdr_hdl);
int __ipa3_release_hdr_proc_ctx(u32 proc_ctx_hdl);
int _ipa_read_ep_reg_v3_0(char *buf, int max_len, int pipe);
--
cgit v1.1