Lucene search

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

Broadcom: Heap overflow in "wl_run_escan" when handling WLC_GET_VALID_CHANNELS ioctl results(CVE-2017-0568)

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

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).

When the โ€œbcmdhdโ€ driver performs a network scan, it does so by calling โ€œwl_run_escanโ€. In configurations where P2P scan is enabled (non-legacy configurations), the function first fetches the list of allowed channels in the current regulatory domain. The channels are fetched by issuing the WLC_GET_VALID_CHANNELS ioctl to the dongle. This ioctlโ€™s results are interpreted as an array of 16-bit values representing channels and a single 32-bit bit value denoting the length of the channel array.

Here is a short snippet from the code handling the P2P scanโ€™s logic:

1.  u16* default_chan_list = kzalloc(num_chans * sizeof(*default_chan_list), GFP_KERNEL);			
2.  u32 n_nodfs = 0
3.  ...
4.  if (!wl_get_valid_channels(ndev, chan_buf, sizeof(chan_buf))) {
5.      list = (wl_uint32_list_t *) chan_buf;
6.      n_valid_chan = dtoh32(list->count);
7.      for (i = 0; i < num_chans; i++)
8.      {
9.          _freq = request->channels[i]->center_freq;
10.         channel = ieee80211_frequency_to_channel(_freq);
11.         ...
12.         for (j = 0; j < n_valid_chan; j++) {
13.             if (channel == (dtoh32(list->element[j])))
14.                 default_chan_list[n_nodfs++] = channel;
15.         }
16.     }
17. }  

Where โ€œwl_get_valid_channelsโ€ is a simple wrapper around the WLC_GET_VALID_CHANNELS ioctl.

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 โ€œlist->countโ€. Doing so would cause the internal loop (lines 12-15) to iterate many times, and each time a value matching โ€œchannelโ€ is encountered, line 14 would be executed. Since there is no validation to make sure that โ€œn_nodfsโ€ does not exceed the size of โ€œnum_chansโ€, this would cause the loop to overflow the allocated chunk for โ€œdefault_chan_listโ€, corrupting the kernelโ€™s memory.

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%