net: wireless: bcmdhd: Fix Android Bug 25662233
Michael Hsu [Fri, 8 Jan 2016 23:16:47 +0000 (15:16 -0800)]
Apply slightly modified version of the following patch.  (Original
patch did not handle 0 length WPS_ID_DEVICE_NAME correctly, so it was
modified to fix 0 length condition.)

Original patch source: https://android.googlesource.com/kernel/msm

Original patch commit message:
> commit 68cdc8df1cb6622980b791ce03e99c255c9888af
> Author: dataanddreams <dataanddreams@gmail.com>
> Date:   Mon Nov 30 17:08:54 2015 -0500
>
>     bcmdhd: Add checks for stack buffer overflows
>
>     These two checks prevent exploitable buffer overflows in two scenarios.
>     1. Long WPS_ID_DEVICE_NAME in WPS info elements
>     2. Invalid SSID determined in certain scan results
>
>     Bug: 25662233
>     Change-Id: Ifb2887737aa6218079745f27d59b5f1364b3892e

Bug 1716690

Change-Id: Ib6bedd8c20185d38a16fb144b6b8ab4393de038f
Signed-off-by: Michael Hsu <mhsu@nvidia.com>
Reviewed-on: http://git-master/r/999649
GVS: Gerrit_Virtual_Submit
Reviewed-by: Manish Tuteja <mtuteja@nvidia.com>
Tested-by: Manish Tuteja <mtuteja@nvidia.com>

drivers/net/wireless/bcmdhd/wl_cfg80211.c

index 8f2751c..ff584b4 100755 (executable)
@@ -1193,8 +1193,9 @@ wl_validate_wps_ie(char *wps_ie, s32 wps_ie_len, bool *pbc)
                        WL_DBG(("  attr WPS_ID_CONFIG_METHODS: %x\n", HTON16(val)));
                } else if (subelt_id == WPS_ID_DEVICE_NAME) {
                        char devname[100];
-                       memcpy(devname, subel, subelt_len);
-                       devname[subelt_len] = '\0';
+                       size_t namelen = MIN(subelt_len, sizeof(devname)-1);
+                       memcpy(devname, subel, namelen);
+                       devname[namelen] = '\0';
                        WL_DBG(("  attr WPS_ID_DEVICE_NAME: %s (len %u)\n",
                                devname, subelt_len));
                } else if (subelt_id == WPS_ID_DEVICE_PWD_ID) {
@@ -10194,9 +10195,9 @@ wl_notify_sched_scan_results(struct bcm_cfg80211 *cfg, struct net_device *ndev,
                         * scan request in the form of cfg80211_scan_request. For timebeing, create
                         * cfg80211_scan_request one out of the received PNO event.
                         */
+                       ssid[i].ssid_len = MIN(DOT11_MAX_SSID_LEN, netinfo->pfnsubnet.SSID_len);
                        memcpy(ssid[i].ssid, netinfo->pfnsubnet.SSID,
-                               netinfo->pfnsubnet.SSID_len);
-                       ssid[i].ssid_len = netinfo->pfnsubnet.SSID_len;
+                              ssid[i].ssid_len);
                        request->n_ssids++;
 
                        channel_req = netinfo->pfnsubnet.channel;