| From foo@baz Sat Jul 28 10:14:30 CEST 2018 |
| From: Alexandre Belloni <alexandre.belloni@bootlin.com> |
| Date: Thu, 17 May 2018 22:48:17 +0200 |
| Subject: rtc: tps6586x: fix possible race condition |
| |
| From: Alexandre Belloni <alexandre.belloni@bootlin.com> |
| |
| [ Upstream commit 63d22063073b0ab46d1e06fe633fb5de8f5c58e1 ] |
| |
| The probe function is not allowed to fail after the RTC is registered |
| because the following may happen: |
| |
| CPU0: CPU1: |
| sys_load_module() |
| do_init_module() |
| do_one_initcall() |
| cmos_do_probe() |
| rtc_device_register() |
| __register_chrdev() |
| cdev->owner = struct module* |
| open("/dev/rtc0") |
| rtc_device_unregister() |
| module_put() |
| free_module() |
| module_free(mod->module_core) |
| /* struct module *module is now |
| freed */ |
| chrdev_open() |
| spin_lock(cdev_lock) |
| cdev_get() |
| try_module_get() |
| module_is_live() |
| /* dereferences already |
| freed struct module* */ |
| |
| Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com> |
| Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/rtc/rtc-tps6586x.c | 14 +++++++++++--- |
| 1 file changed, 11 insertions(+), 3 deletions(-) |
| |
| --- a/drivers/rtc/rtc-tps6586x.c |
| +++ b/drivers/rtc/rtc-tps6586x.c |
| @@ -276,14 +276,15 @@ static int tps6586x_rtc_probe(struct pla |
| device_init_wakeup(&pdev->dev, 1); |
| |
| platform_set_drvdata(pdev, rtc); |
| - rtc->rtc = devm_rtc_device_register(&pdev->dev, dev_name(&pdev->dev), |
| - &tps6586x_rtc_ops, THIS_MODULE); |
| + rtc->rtc = devm_rtc_allocate_device(&pdev->dev); |
| if (IS_ERR(rtc->rtc)) { |
| ret = PTR_ERR(rtc->rtc); |
| - dev_err(&pdev->dev, "RTC device register: ret %d\n", ret); |
| + dev_err(&pdev->dev, "RTC allocate device: ret %d\n", ret); |
| goto fail_rtc_register; |
| } |
| |
| + rtc->rtc->ops = &tps6586x_rtc_ops; |
| + |
| ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL, |
| tps6586x_rtc_irq, |
| IRQF_ONESHOT, |
| @@ -294,6 +295,13 @@ static int tps6586x_rtc_probe(struct pla |
| goto fail_rtc_register; |
| } |
| disable_irq(rtc->irq); |
| + |
| + ret = rtc_register_device(rtc->rtc); |
| + if (ret) { |
| + dev_err(&pdev->dev, "RTC device register: ret %d\n", ret); |
| + goto fail_rtc_register; |
| + } |
| + |
| return 0; |
| |
| fail_rtc_register: |