0ed148188b0ce0436c40b8ad3ce1856c66b49cf7
[openwrt/staging/jow.git] /
1 From b72c51a58e6d63ef673ac96b8ab5bc98799c5f7b Mon Sep 17 00:00:00 2001
2 From: Lyude Paul <lyude@redhat.com>
3 Date: Sat, 24 Nov 2018 17:57:05 -0500
4 Subject: [PATCH] brcmfmac: Fix out of bounds memory access during fw load
5
6 I ended up tracking down some rather nasty issues with f2fs (and other
7 filesystem modules) constantly crashing on my kernel down to a
8 combination of out of bounds memory accesses, one of which was coming
9 from brcmfmac during module load:
10
11 [ 30.891382] brcmfmac: brcmf_fw_alloc_request: using brcm/brcmfmac4356-sdio for chip BCM4356/2
12 [ 30.894437] ==================================================================
13 [ 30.901581] BUG: KASAN: global-out-of-bounds in brcmf_fw_alloc_request+0x42c/0x480 [brcmfmac]
14 [ 30.909935] Read of size 1 at addr ffff2000024865df by task kworker/6:2/387
15 [ 30.916805]
16 [ 30.918261] CPU: 6 PID: 387 Comm: kworker/6:2 Tainted: G O 4.20.0-rc3Lyude-Test+ #19
17 [ 30.927251] Hardware name: amlogic khadas-vim2/khadas-vim2, BIOS 2018.07-rc2-armbian 09/11/2018
18 [ 30.935964] Workqueue: events brcmf_driver_register [brcmfmac]
19 [ 30.941641] Call trace:
20 [ 30.944058] dump_backtrace+0x0/0x3e8
21 [ 30.947676] show_stack+0x14/0x20
22 [ 30.950968] dump_stack+0x130/0x1c4
23 [ 30.954406] print_address_description+0x60/0x25c
24 [ 30.959066] kasan_report+0x1b4/0x368
25 [ 30.962683] __asan_report_load1_noabort+0x18/0x20
26 [ 30.967547] brcmf_fw_alloc_request+0x42c/0x480 [brcmfmac]
27 [ 30.967639] brcmf_sdio_probe+0x163c/0x2050 [brcmfmac]
28 [ 30.978035] brcmf_ops_sdio_probe+0x598/0xa08 [brcmfmac]
29 [ 30.983254] sdio_bus_probe+0x190/0x398
30 [ 30.983270] really_probe+0x2a0/0xa70
31 [ 30.983296] driver_probe_device+0x1b4/0x2d8
32 [ 30.994901] __driver_attach+0x200/0x280
33 [ 30.994914] bus_for_each_dev+0x10c/0x1a8
34 [ 30.994925] driver_attach+0x38/0x50
35 [ 30.994935] bus_add_driver+0x330/0x608
36 [ 30.994953] driver_register+0x140/0x388
37 [ 31.013965] sdio_register_driver+0x74/0xa0
38 [ 31.014076] brcmf_sdio_register+0x14/0x60 [brcmfmac]
39 [ 31.023177] brcmf_driver_register+0xc/0x18 [brcmfmac]
40 [ 31.023209] process_one_work+0x654/0x1080
41 [ 31.032266] worker_thread+0x4f0/0x1308
42 [ 31.032286] kthread+0x2a8/0x320
43 [ 31.039254] ret_from_fork+0x10/0x1c
44 [ 31.039269]
45 [ 31.044226] The buggy address belongs to the variable:
46 [ 31.044351] brcmf_firmware_path+0x11f/0xfffffffffffd3b40 [brcmfmac]
47 [ 31.055601]
48 [ 31.057031] Memory state around the buggy address:
49 [ 31.061800] ffff200002486480: 04 fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
50 [ 31.068983] ffff200002486500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
51 [ 31.068993] >ffff200002486580: 00 00 00 00 00 00 00 00 fa fa fa fa 00 00 00 00
52 [ 31.068999] ^
53 [ 31.069017] ffff200002486600: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
54 [ 31.096521] ffff200002486680: 00 00 00 00 00 00 00 00 00 00 00 00 fa fa fa fa
55 [ 31.096528] ==================================================================
56 [ 31.096533] Disabling lock debugging due to kernel taint
57
58 It appears that when trying to determine the length of the string in the
59 alternate firmware path, we make the mistake of not handling the case
60 where the firmware path is empty correctly. Since strlen(mp_path) can
61 return 0, we'll end up accessing mp_path[-1] when the firmware_path
62 isn't provided through the module arguments.
63
64 So, fix this by just setting the end char to '\0' by default, and only
65 changing it if we have a non-zero length. Additionally, use strnlen()
66 with BRCMF_FW_ALTPATH_LEN instead of strlen() just to be extra safe.
67
68 Fixes: 2baa3aaee27f ("brcmfmac: introduce brcmf_fw_alloc_request() function")
69 Cc: Hante Meuleman <hante.meuleman@broadcom.com>
70 Cc: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
71 Cc: Franky Lin <franky.lin@broadcom.com>
72 Cc: Arend van Spriel <arend.vanspriel@broadcom.com>
73 Cc: Kalle Valo <kvalo@codeaurora.org>
74 Cc: Arend Van Spriel <arend.vanspriel@broadcom.com>
75 Cc: Himanshu Jha <himanshujha199640@gmail.com>
76 Cc: Dan Haab <dhaab@luxul.com>
77 Cc: Jia-Shyr Chuang <saint.chuang@cypress.com>
78 Cc: Ian Molton <ian@mnementh.co.uk>
79 Cc: <stable@vger.kernel.org> # v4.17+
80 Signed-off-by: Lyude Paul <lyude@redhat.com>
81 Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
82 ---
83 .../net/wireless/broadcom/brcm80211/brcmfmac/firmware.c | 8 ++++++--
84 1 file changed, 6 insertions(+), 2 deletions(-)
85
86 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
87 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
88 @@ -708,8 +708,9 @@ brcmf_fw_alloc_request(u32 chip, u32 chi
89 struct brcmf_fw_request *fwreq;
90 char chipname[12];
91 const char *mp_path;
92 + size_t mp_path_len;
93 u32 i, j;
94 - char end;
95 + char end = '\0';
96 size_t reqsz;
97
98 for (i = 0; i < table_size; i++) {
99 @@ -734,7 +735,10 @@ brcmf_fw_alloc_request(u32 chip, u32 chi
100 mapping_table[i].fw_base, chipname);
101
102 mp_path = brcmf_mp_global.firmware_path;
103 - end = mp_path[strlen(mp_path) - 1];
104 + mp_path_len = strnlen(mp_path, BRCMF_FW_ALTPATH_LEN);
105 + if (mp_path_len)
106 + end = mp_path[mp_path_len - 1];
107 +
108 fwreq->n_items = n_fwnames;
109
110 for (j = 0; j < n_fwnames; j++) {