mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2024-10-01 01:35:54 -04:00
121 lines
4.2 KiB
Diff
121 lines
4.2 KiB
Diff
|
From 068427b76963929b220a4be40cdf77856374df55 Mon Sep 17 00:00:00 2001
|
||
|
From: Sudhir Kohalli <sudhir.kohalli@broadcom.com>
|
||
|
Date: Fri, 4 Nov 2016 12:09:19 -0700
|
||
|
Subject: [PATCH] net: wireless: bcmdhd: Security V: memory overflow in wifi
|
||
|
driver function __dhd_apf_add_filter
|
||
|
|
||
|
In order to fix the memory overflow added a check
|
||
|
for APF program_len to verify if the program_len is
|
||
|
more than the MAX program length. If the APF program_len
|
||
|
is more than the MAX APF program_len then parse an error.
|
||
|
This check will avoid memory oveflow issue happening
|
||
|
in __dhd_apf_add_filter API. APF referes to Android Packet
|
||
|
filter.
|
||
|
|
||
|
Bug: 32219121
|
||
|
|
||
|
Change-Id: Ibe468dcb51ec4f35c64da4bdc7296130bf145f13
|
||
|
Signed-off-by: Sudhir Kohalli <sudhir.kohalli@broadcom.com>
|
||
|
---
|
||
|
drivers/net/wireless/bcmdhd/dhd_linux.c | 13 ++++++++++-
|
||
|
drivers/net/wireless/bcmdhd/include/wlioctl.h | 2 ++
|
||
|
drivers/net/wireless/bcmdhd/wl_cfgvendor.c | 31 +++++++++++++++++++++++++--
|
||
|
3 files changed, 43 insertions(+), 3 deletions(-)
|
||
|
|
||
|
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c
|
||
|
index 4ce5a2f4663d3..2fd2934a7e851 100644
|
||
|
--- a/drivers/net/wireless/bcmdhd/dhd_linux.c
|
||
|
+++ b/drivers/net/wireless/bcmdhd/dhd_linux.c
|
||
|
@@ -9039,13 +9039,24 @@ __dhd_apf_add_filter(struct net_device *ndev, uint32 filter_id,
|
||
|
}
|
||
|
|
||
|
cmd_len = sizeof(cmd);
|
||
|
+
|
||
|
+ /* Check if the program_len is more than the expected len
|
||
|
+ * and if program is initialized to NULL return here.
|
||
|
+ */
|
||
|
+ if ((program_len > WL_APF_PROGRAM_MAX_SIZE) ||
|
||
|
+ (program == NULL)) {
|
||
|
+ DHD_ERROR(("%s Invalid program_len: %d, program: %pK\n",
|
||
|
+ __func__, program_len, program));
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
buf_len = cmd_len + WL_PKT_FILTER_FIXED_LEN +
|
||
|
WL_APF_PROGRAM_FIXED_LEN + program_len;
|
||
|
|
||
|
kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
|
||
|
buf = kzalloc(buf_len, kflags);
|
||
|
if (unlikely(!buf)) {
|
||
|
- DHD_ERROR(("%s: MALLOC failure, %d bytes\n", __FUNCTION__, buf_len));
|
||
|
+ DHD_ERROR(("%s: MALLOC failure, %d bytes\n", __func__,
|
||
|
+ buf_len));
|
||
|
return -ENOMEM;
|
||
|
}
|
||
|
|
||
|
diff --git a/drivers/net/wireless/bcmdhd/include/wlioctl.h b/drivers/net/wireless/bcmdhd/include/wlioctl.h
|
||
|
index 50de89bc5a9c6..808a0bfc3e108 100644
|
||
|
--- a/drivers/net/wireless/bcmdhd/include/wlioctl.h
|
||
|
+++ b/drivers/net/wireless/bcmdhd/include/wlioctl.h
|
||
|
@@ -3291,6 +3291,8 @@ typedef struct wl_tcp_keep_set {
|
||
|
OFFSETOF(wl_pkt_filter_pattern_listel_t, mask_and_data)
|
||
|
|
||
|
#define WL_APF_INTERNAL_VERSION 1
|
||
|
+/* This will be MAX allowable APF program size */
|
||
|
+#define WL_APF_PROGRAM_MAX_SIZE (2 * 1024)
|
||
|
#define WL_APF_PROGRAM_FIXED_LEN OFFSETOF(wl_apf_program_t, instrs)
|
||
|
#define WL_APF_PROGRAM_LEN(apf_program) \
|
||
|
(apf_program->instr_len * sizeof(apf_program->instrs[0]))
|
||
|
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c
|
||
|
index d578026885619..5be16a72aa43f 100644
|
||
|
--- a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c
|
||
|
+++ b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c
|
||
|
@@ -2722,12 +2722,33 @@ wl_cfgvendor_apf_set_filter(struct wiphy *wiphy,
|
||
|
int ret, tmp, type;
|
||
|
gfp_t kflags;
|
||
|
|
||
|
- /* assumption: length attribute must come first */
|
||
|
+ if (len <= 0) {
|
||
|
+ WL_ERR((" Invalid len : %d\n", len));
|
||
|
+ ret = -EINVAL;
|
||
|
+ goto exit;
|
||
|
+ }
|
||
|
nla_for_each_attr(iter, data, len, tmp) {
|
||
|
type = nla_type(iter);
|
||
|
switch (type) {
|
||
|
case APF_ATTRIBUTE_PROGRAM_LEN:
|
||
|
- program_len = nla_get_u32(iter);
|
||
|
+ /* check if the iter is valid and program
|
||
|
+ * length is not already initialized.
|
||
|
+ */
|
||
|
+ if (nla_len(iter) == sizeof(uint32) &&
|
||
|
+ !program_len) {
|
||
|
+ program_len = nla_get_u32(iter);
|
||
|
+ } else {
|
||
|
+ ret = -EINVAL;
|
||
|
+ goto exit;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (program_len >
|
||
|
+ WL_APF_PROGRAM_MAX_SIZE) {
|
||
|
+ WL_ERR(("program len is more "));
|
||
|
+ WL_ERR(("than expected len\n"));
|
||
|
+ ret = -EINVAL;
|
||
|
+ goto exit;
|
||
|
+ }
|
||
|
if (unlikely(!program_len)) {
|
||
|
WL_ERR(("zero program length\n"));
|
||
|
ret = -EINVAL;
|
||
|
@@ -2740,6 +2761,12 @@ wl_cfgvendor_apf_set_filter(struct wiphy *wiphy,
|
||
|
ret = -EINVAL;
|
||
|
goto exit;
|
||
|
}
|
||
|
+ if (nla_len(iter) != program_len) {
|
||
|
+ WL_ERR(("program_len is not same\n"));
|
||
|
+ ret = -EINVAL;
|
||
|
+ goto exit;
|
||
|
+ }
|
||
|
+
|
||
|
kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
|
||
|
program = kzalloc(program_len, kflags);
|
||
|
if (unlikely(!program)) {
|