DivestOS/Patches/Linux_CVEs/CVE-2016-8464/3.18/0002.patch
2017-11-07 17:32:46 -05:00

166 lines
4.8 KiB
Diff

diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c
index 24b71c5..0db69ef 100644
--- a/drivers/net/wireless/bcmdhd/wl_android.c
+++ b/drivers/net/wireless/bcmdhd/wl_android.c
@@ -246,11 +246,18 @@
return -1;
if ((ssid.SSID_len == 0) || (ssid.SSID_len > DOT11_MAX_SSID_LEN)) {
DHD_ERROR(("%s: wldev_get_ssid failed\n", __FUNCTION__));
+ } else if (total_len <= ssid.SSID_len) {
+ return -ENOMEM;
} else {
memcpy(command, ssid.SSID, ssid.SSID_len);
bytes_written = ssid.SSID_len;
}
- bytes_written += snprintf(&command[bytes_written], total_len, " rssi %d", rssi);
+ if ((total_len - bytes_written) < (strlen(" rssi -XXX") + 1))
+ return -ENOMEM;
+ bytes_written += scnprintf(&command[bytes_written],
+ total_len - bytes_written, " rssi %d", rssi);
+ command[bytes_written] = '\0';
+
DHD_INFO(("%s: command result is %s (%d)\n", __FUNCTION__, command, bytes_written));
return bytes_written;
}
@@ -1284,10 +1291,13 @@
int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
{
#define PRIVATE_COMMAND_MAX_LEN 8192
+#define PRIVATE_COMMAND_DEF_LEN 4096
+
int ret = 0;
char *command = NULL;
int bytes_written = 0;
android_wifi_priv_cmd priv_cmd;
+ int buf_size = 0;
net_os_wake_lock(net);
@@ -1321,12 +1331,17 @@
goto exit;
}
}
+
if ((priv_cmd.total_len > PRIVATE_COMMAND_MAX_LEN) || (priv_cmd.total_len < 0)) {
- DHD_ERROR(("%s: too long priavte command\n", __FUNCTION__));
+ DHD_ERROR(("%s: buf length invalid:%d\n", __FUNCTION__,
+ priv_cmd.total_len));
ret = -EINVAL;
goto exit;
}
- command = kmalloc((priv_cmd.total_len + 1), GFP_KERNEL);
+
+ buf_size = max(priv_cmd.total_len, PRIVATE_COMMAND_DEF_LEN);
+ command = kmalloc((buf_size + 1), GFP_KERNEL);
+
if (!command)
{
DHD_ERROR(("%s: failed to allocate memory\n", __FUNCTION__));
@@ -1341,6 +1356,41 @@
DHD_INFO(("%s: Android private cmd \"%s\" on %s\n", __FUNCTION__, command, ifr->ifr_name));
+ bytes_written = wl_handle_private_cmd(net, command, priv_cmd.total_len);
+ if (bytes_written >= 0) {
+ if ((bytes_written == 0) && (priv_cmd.total_len > 0))
+ command[0] = '\0';
+ if (bytes_written >= priv_cmd.total_len) {
+ DHD_ERROR(("%s: err. b_w:%d >= tot:%d\n", __FUNCTION__,
+ bytes_written, priv_cmd.total_len));
+ ret = BCME_BUFTOOSHORT;
+ goto exit;
+ }
+ bytes_written++;
+ priv_cmd.used_len = bytes_written;
+ if (copy_to_user(priv_cmd.buf, command, bytes_written)) {
+ DHD_ERROR(("%s: failed copy to user\n", __FUNCTION__));
+ ret = -EFAULT;
+ }
+ } else {
+ ret = bytes_written;
+ }
+
+exit:
+ net_os_wake_unlock(net);
+ kfree(command);
+ return ret;
+}
+
+int
+wl_handle_private_cmd(struct net_device *net, char *command, u32 buf_size)
+{
+ int bytes_written = 0;
+ android_wifi_priv_cmd priv_cmd;
+
+ bzero(&priv_cmd, sizeof(android_wifi_priv_cmd));
+ priv_cmd.total_len = buf_size;
+
if (strnicmp(command, CMD_START, strlen(CMD_START)) == 0) {
DHD_INFO(("%s, Received regular START command\n", __FUNCTION__));
bytes_written = wl_android_wifi_on(net);
@@ -1350,10 +1400,9 @@
}
if (!g_wifi_on) {
- DHD_ERROR(("%s: Ignore private cmd \"%s\" - iface %s is down\n",
- __FUNCTION__, command, ifr->ifr_name));
- ret = 0;
- goto exit;
+ DHD_ERROR(("%s: Ignore private cmd \"%s\" - iface is down\n",
+ __FUNCTION__, command));
+ return 0;
}
if (strnicmp(command, CMD_STOP, strlen(CMD_STOP)) == 0) {
@@ -1511,36 +1560,10 @@
}
else {
DHD_ERROR(("Unknown PRIVATE command %s - ignored\n", command));
- snprintf(command, 3, "OK");
- bytes_written = strlen("OK");
+ bytes_written = scnprintf(command, sizeof("FAIL"), "FAIL");
}
- if (bytes_written >= 0) {
- if ((bytes_written == 0) && (priv_cmd.total_len > 0))
- command[0] = '\0';
- if (bytes_written >= priv_cmd.total_len) {
- DHD_ERROR(("%s: bytes_written = %d\n", __FUNCTION__, bytes_written));
- bytes_written = priv_cmd.total_len;
- } else {
- bytes_written++;
- }
- priv_cmd.used_len = bytes_written;
- if (copy_to_user(priv_cmd.buf, command, bytes_written)) {
- DHD_ERROR(("%s: failed to copy data to user buffer\n", __FUNCTION__));
- ret = -EFAULT;
- }
- }
- else {
- ret = bytes_written;
- }
-
-exit:
- net_os_wake_unlock(net);
- if (command) {
- kfree(command);
- }
-
- return ret;
+ return bytes_written;
}
int wl_android_init(void)
diff --git a/drivers/net/wireless/bcmdhd/wl_android.h b/drivers/net/wireless/bcmdhd/wl_android.h
index 2827132..f62b646 100644
--- a/drivers/net/wireless/bcmdhd/wl_android.h
+++ b/drivers/net/wireless/bcmdhd/wl_android.h
@@ -53,6 +53,7 @@
int wl_android_wifi_on(struct net_device *dev);
int wl_android_wifi_off(struct net_device *dev, bool on_failure);
int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd);
+int wl_handle_private_cmd(struct net_device *net, char *command, u32 cmd_len);
/* hostap mac mode */