diff options
author | Alexandre Belloni <alexandre.belloni@bootlin.com> | 2018-06-04 14:05:40 +0200 |
---|---|---|
committer | Alexandre Belloni <alexandre.belloni@bootlin.com> | 2018-06-04 14:36:14 +0200 |
commit | 29615d03ccc0f8f01b45178737600810d8bf971f (patch) | |
tree | 5eeb0fd992473e03dc6a711c8b8e1bf30a9d543c /drivers/rtc | |
parent | 696fa1d043ecd605166cc97b24c0b7a59dd5a135 (diff) | |
download | linux-29615d03ccc0f8f01b45178737600810d8bf971f.tar.bz2 |
rtc: sunxi: fix possible race condition
The IRQ is requested before the struct rtc is allocated and registered, but
this struct is used in the IRQ handler. This may lead to a NULL pointer
dereference.
Switch to devm_rtc_allocate_device/rtc_register_device to allocate the rtc
before requesting the IRQ.
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/rtc-sunxi.c | 23 |
1 files changed, 9 insertions, 14 deletions
diff --git a/drivers/rtc/rtc-sunxi.c b/drivers/rtc/rtc-sunxi.c index dadbf8b324ad..21865d3d8fe8 100644 --- a/drivers/rtc/rtc-sunxi.c +++ b/drivers/rtc/rtc-sunxi.c @@ -445,6 +445,10 @@ static int sunxi_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, chip); chip->dev = &pdev->dev; + chip->rtc = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(chip->rtc)) + return PTR_ERR(chip->rtc); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); chip->base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(chip->base)) @@ -481,11 +485,12 @@ static int sunxi_rtc_probe(struct platform_device *pdev) writel(SUNXI_ALRM_IRQ_STA_CNT_IRQ_PEND, chip->base + SUNXI_ALRM_IRQ_STA); - chip->rtc = rtc_device_register("rtc-sunxi", &pdev->dev, - &sunxi_rtc_ops, THIS_MODULE); - if (IS_ERR(chip->rtc)) { + chip->rtc->ops = &sunxi_rtc_ops; + + ret = rtc_register_device(chip->rtc); + if (ret) { dev_err(&pdev->dev, "unable to register device\n"); - return PTR_ERR(chip->rtc); + return ret; } dev_info(&pdev->dev, "RTC enabled\n"); @@ -493,18 +498,8 @@ static int sunxi_rtc_probe(struct platform_device *pdev) return 0; } -static int sunxi_rtc_remove(struct platform_device *pdev) -{ - struct sunxi_rtc_dev *chip = platform_get_drvdata(pdev); - - rtc_device_unregister(chip->rtc); - - return 0; -} - static struct platform_driver sunxi_rtc_driver = { .probe = sunxi_rtc_probe, - .remove = sunxi_rtc_remove, .driver = { .name = "sunxi-rtc", .of_match_table = sunxi_rtc_dt_ids, |