Lucene search

K
seebugRootSSV:92899
HistoryApr 05, 2017 - 12:00 a.m.

Broadcom: Heap overflow in "wl_iw_get_essid" when handling WLC_GET_SSID ioctl results(CVE-2017-0570)

2017-04-0500:00:00
Root
www.seebug.org
21

0.002 Low

EPSS

Percentile

51.4%

Broadcom produces Wi-Fi HardMAC SoCs which are used to handle the PHY and MAC layer processing. These chips are present in both mobile devices and Wi-Fi routers, and are capable of handling many Wi-Fi related events without delegating to the host OS. On Android devices, the โ€œbcmdhdโ€ driver is used in order to communicate with the Wi-Fi SoC (also referred to as โ€œdongleโ€).

Along with the regular flow of frames transferred between the host and the dongle, the two communicate with one another via a set of โ€œioctlsโ€ which can be issued to read or write dongle configuration from the host. This information is exchanged using the SDIO โ€œcontrolโ€ channel (SDPCM_CONTROL_CHANNEL) rather than the regular โ€œdataโ€ and โ€œglomโ€ channels (which are used to transfer frames).

โ€œbcmdhdโ€ registers a set of handlers to support IW ioctls (which may be invoked on a socket descriptors where โ€œiwreq.ifrnameโ€ points to a device entry exposed by the โ€œbcmdhdโ€ driver). These ioctls are handled by the โ€œwl_iw_ioctlโ€ function. The function first allocates an โ€œextrasโ€ buffer of an appropriate size, according to the ioctl issued. Then, the function looks up the handler function matching the issued ioctl and invokes it, passing the allocated โ€œextrasโ€ buffer as an argument.

When the โ€œSIOCGIWESSIDโ€ ioctl is invoked (in order to query the current ESSID), the function allocates an extras buffer of size 33, and then invokes the internal handler function, โ€œwl_iw_get_essidโ€. Here is a short snippet from the handler:

1.  wl_iw_get_essid(struct net_device *dev, struct iw_request_info *info,
2.                  struct iw_point *dwrq, char *extra)
3.  {
4.      wlc_ssid_t ssid;
5.      int error;
6.      if ((error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid)))) {
7.          WL_ERROR(("Error getting the SSID\n"));
8.          return error;
9.      }
10.     ssid.SSID_len = dtoh32(ssid.SSID_len);
11.     memcpy(extra, ssid.SSID, ssid.SSID_len);
12.     ...
13. }

Where โ€œextraโ€ is the extras buffer of size 33, allocated by โ€œwl_iw_ioctlโ€.

As can be seen above, the handler trusts the value of โ€œssid.SSID_lenโ€. An attacker controlling the dongle can re-write the ioctl handling function (since it is entirely RAM-resident), in order to control the results of the ioctl above. This would allow the attacker to return an arbitrarily large value for โ€œssid.SSID_lenโ€, causing the memcpy operation (line 11) to overflow the โ€œextraโ€ buffer.

Iโ€™ve been able to statically verify this issue on the โ€œbcmdhd-3.10โ€ driver, and in the corresponding โ€œbcmdhdโ€ driver on the Nexus 5 (hammerhead) and Nexus 6Pโ€™s (angler) kernels.

0.002 Low

EPSS

Percentile

51.4%