Skip to content

Commit db4efbb

Browse files
Arend van Spriellinvjw
Arend van Spriel
authored andcommitted
brcmfmac: obtain platform data upon module initialization
The driver uses platform_driver_probe() to obtain platform data if any. However, that function is placed in the .init section so it must be called upon driver module initialization. The problem was reported by Fenguang Wu resulting in a kernel oops because the .init section was already freed. [ 48.966342] Switched to clocksource tsc [ 48.970002] kernel tried to execute NX-protected page - exploit attempt? (uid: 0) [ 48.970851] BUG: unable to handle kernel paging request at ffffffff82196446 [ 48.970957] IP: [<ffffffff82196446>] classes_init+0x26/0x26 [ 48.970957] PGD 1e76067 PUD 1e77063 PMD f388063 PTE 8000000002196163 [ 48.970957] Oops: 0011 [#1] [ 48.970957] CPU: 0 PID: 17 Comm: kworker/0:1 Not tainted 3.11.0-rc7-00444-gc52dd7f #23 [ 48.970957] Workqueue: events brcmf_driver_init [ 48.970957] task: ffff8800001d2000 ti: ffff8800001d4000 task.ti: ffff8800001d4000 [ 48.970957] RIP: 0010:[<ffffffff82196446>] [<ffffffff82196446>] classes_init+0x26/0x26 [ 48.970957] RSP: 0000:ffff8800001d5d40 EFLAGS: 00000286 [ 48.970957] RAX: 0000000000000001 RBX: ffffffff820c5620 RCX: 0000000000000000 [ 48.970957] RDX: 0000000000000001 RSI: ffffffff816f7380 RDI: ffffffff820c56c0 [ 48.970957] RBP: ffff8800001d5d50 R08: ffff8800001d2508 R09: 0000000000000002 [ 48.970957] R10: 0000000000000000 R11: 0001f7ce298c5620 R12: ffff8800001c76b0 [ 48.970957] R13: ffffffff81e91d40 R14: 0000000000000000 R15: ffff88000e0ce300 [ 48.970957] FS: 0000000000000000(0000) GS:ffffffff81e84000(0000) knlGS:0000000000000000 [ 48.970957] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b [ 48.970957] CR2: ffffffff82196446 CR3: 0000000001e75000 CR4: 00000000000006b0 [ 48.970957] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 48.970957] DR3: 0000000000000000 DR6: 0000000000000000 DR7: 0000000000000000 [ 48.970957] Stack: [ 48.970957] ffffffff816f7df8 ffffffff820c5620 ffff8800001d5d60 ffffffff816eeec9 [ 48.970957] ffff8800001d5de0 ffffffff81073dc5 ffffffff81073d68 ffff8800001d5db8 [ 48.970957] 0000000000000086 ffffffff820c5620 ffffffff824f7fd0 0000000000000000 [ 48.970957] Call Trace: [ 48.970957] [<ffffffff816f7df8>] ? brcmf_sdio_init+0x18/0x70 [ 48.970957] [<ffffffff816eeec9>] brcmf_driver_init+0x9/0x10 [ 48.970957] [<ffffffff81073dc5>] process_one_work+0x1d5/0x480 [ 48.970957] [<ffffffff81073d68>] ? process_one_work+0x178/0x480 [ 48.970957] [<ffffffff81074188>] worker_thread+0x118/0x3a0 [ 48.970957] [<ffffffff81074070>] ? process_one_work+0x480/0x480 [ 48.970957] [<ffffffff8107aa17>] kthread+0xe7/0xf0 [ 48.970957] [<ffffffff810829f7>] ? finish_task_switch.constprop.57+0x37/0xd0 [ 48.970957] [<ffffffff8107a930>] ? __kthread_parkme+0x80/0x80 [ 48.970957] [<ffffffff81a6923a>] ret_from_fork+0x7a/0xb0 [ 48.970957] [<ffffffff8107a930>] ? __kthread_parkme+0x80/0x80 [ 48.970957] Code: cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc <cc> cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc [ 48.970957] RIP [<ffffffff82196446>] classes_init+0x26/0x26 [ 48.970957] RSP <ffff8800001d5d40> [ 48.970957] CR2: ffffffff82196446 [ 48.970957] ---[ end trace 62980817cd525f14 ]--- Cc: <[email protected]> # 3.10.x, 3.11.x Reported-by: Fengguang Wu <[email protected]> Reviewed-by: Hante Meuleman <[email protected]> Reviewed-by: Pieter-Paul Giesberts <[email protected]> Tested-by: Fengguang Wu <[email protected]> Signed-off-by: Arend van Spriel <[email protected]> Signed-off-by: John W. Linville <[email protected]>
1 parent 346ece0 commit db4efbb

File tree

4 files changed

+24
-23
lines changed

4 files changed

+24
-23
lines changed

drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -464,20 +464,14 @@ static struct sdio_driver brcmf_sdmmc_driver = {
464464

465465
static int brcmf_sdio_pd_probe(struct platform_device *pdev)
466466
{
467-
int ret;
468-
469467
brcmf_dbg(SDIO, "Enter\n");
470468

471469
brcmfmac_sdio_pdata = pdev->dev.platform_data;
472470

473471
if (brcmfmac_sdio_pdata->power_on)
474472
brcmfmac_sdio_pdata->power_on();
475473

476-
ret = sdio_register_driver(&brcmf_sdmmc_driver);
477-
if (ret)
478-
brcmf_err("sdio_register_driver failed: %d\n", ret);
479-
480-
return ret;
474+
return 0;
481475
}
482476

483477
static int brcmf_sdio_pd_remove(struct platform_device *pdev)
@@ -500,6 +494,15 @@ static struct platform_driver brcmf_sdio_pd = {
500494
}
501495
};
502496

497+
void brcmf_sdio_register(void)
498+
{
499+
int ret;
500+
501+
ret = sdio_register_driver(&brcmf_sdmmc_driver);
502+
if (ret)
503+
brcmf_err("sdio_register_driver failed: %d\n", ret);
504+
}
505+
503506
void brcmf_sdio_exit(void)
504507
{
505508
brcmf_dbg(SDIO, "Enter\n");
@@ -510,18 +513,13 @@ void brcmf_sdio_exit(void)
510513
sdio_unregister_driver(&brcmf_sdmmc_driver);
511514
}
512515

513-
void brcmf_sdio_init(void)
516+
void __init brcmf_sdio_init(void)
514517
{
515518
int ret;
516519

517520
brcmf_dbg(SDIO, "Enter\n");
518521

519522
ret = platform_driver_probe(&brcmf_sdio_pd, brcmf_sdio_pd_probe);
520-
if (ret == -ENODEV) {
521-
brcmf_dbg(SDIO, "No platform data available, registering without.\n");
522-
ret = sdio_register_driver(&brcmf_sdmmc_driver);
523-
}
524-
525-
if (ret)
526-
brcmf_err("driver registration failed: %d\n", ret);
523+
if (ret == -ENODEV)
524+
brcmf_dbg(SDIO, "No platform data available.\n");
527525
}

drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,11 @@ extern int brcmf_bus_start(struct device *dev);
156156
#ifdef CONFIG_BRCMFMAC_SDIO
157157
extern void brcmf_sdio_exit(void);
158158
extern void brcmf_sdio_init(void);
159+
extern void brcmf_sdio_register(void);
159160
#endif
160161
#ifdef CONFIG_BRCMFMAC_USB
161162
extern void brcmf_usb_exit(void);
162-
extern void brcmf_usb_init(void);
163+
extern void brcmf_usb_register(void);
163164
#endif
164165

165166
#endif /* _BRCMF_BUS_H_ */

drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1231,21 +1231,23 @@ u32 brcmf_get_chip_info(struct brcmf_if *ifp)
12311231
return bus->chip << 4 | bus->chiprev;
12321232
}
12331233

1234-
static void brcmf_driver_init(struct work_struct *work)
1234+
static void brcmf_driver_register(struct work_struct *work)
12351235
{
1236-
brcmf_debugfs_init();
1237-
12381236
#ifdef CONFIG_BRCMFMAC_SDIO
1239-
brcmf_sdio_init();
1237+
brcmf_sdio_register();
12401238
#endif
12411239
#ifdef CONFIG_BRCMFMAC_USB
1242-
brcmf_usb_init();
1240+
brcmf_usb_register();
12431241
#endif
12441242
}
1245-
static DECLARE_WORK(brcmf_driver_work, brcmf_driver_init);
1243+
static DECLARE_WORK(brcmf_driver_work, brcmf_driver_register);
12461244

12471245
static int __init brcmfmac_module_init(void)
12481246
{
1247+
brcmf_debugfs_init();
1248+
#ifdef CONFIG_BRCMFMAC_SDIO
1249+
brcmf_sdio_init();
1250+
#endif
12491251
if (!schedule_work(&brcmf_driver_work))
12501252
return -EBUSY;
12511253

drivers/net/wireless/brcm80211/brcmfmac/usb.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1539,7 +1539,7 @@ void brcmf_usb_exit(void)
15391539
brcmf_release_fw(&fw_image_list);
15401540
}
15411541

1542-
void brcmf_usb_init(void)
1542+
void brcmf_usb_register(void)
15431543
{
15441544
brcmf_dbg(USB, "Enter\n");
15451545
INIT_LIST_HEAD(&fw_image_list);

0 commit comments

Comments
 (0)