From 789c1093f02c436b320d78a739f9610c8271cb73 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Mon, 11 Oct 2021 21:21:14 +0800 Subject: rtc: class: don't call cdev_device_del() when cdev_device_add() failed I got a null-ptr-deref report when doing fault injection test: general protection fault, probably for non-canonical address 0xdffffc0000000022: 0000 [#1] SMP KASAN PTI KASAN: null-ptr-deref in range [0x0000000000000110-0x0000000000000117] RIP: 0010:device_del+0x132/0xdc0 Call Trace: cdev_device_del+0x1a/0x80 devm_rtc_unregister_device+0x37/0x80 release_nodes+0xc3/0x3b0 If cdev_device_add() fails, 'dev->p' is not set, it causes null-ptr-deref when calling cdev_device_del(). Registering character device is optional, we don't return error code here, so introduce a new flag 'RTC_NO_CDEV' to indicate if it has character device, cdev_device_del() is called when this bit is not set. Reported-by: Hulk Robot Signed-off-by: Yang Yingliang Signed-off-by: Alexandre Belloni Link: https://lore.kernel.org/r/20211011132114.3663509-1-yangyingliang@huawei.com --- drivers/rtc/class.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/rtc/class.c') diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index f77bc089eb6b..654e921244bf 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -334,7 +334,8 @@ static void devm_rtc_unregister_device(void *data) * letting any rtc_class_open() users access it again */ rtc_proc_del_device(rtc); - cdev_device_del(&rtc->char_dev, &rtc->dev); + if (!test_bit(RTC_NO_CDEV, &rtc->flags)) + cdev_device_del(&rtc->char_dev, &rtc->dev); rtc->ops = NULL; mutex_unlock(&rtc->ops_lock); } @@ -397,12 +398,14 @@ int __devm_rtc_register_device(struct module *owner, struct rtc_device *rtc) rtc_dev_prepare(rtc); err = cdev_device_add(&rtc->char_dev, &rtc->dev); - if (err) + if (err) { + set_bit(RTC_NO_CDEV, &rtc->flags); dev_warn(rtc->dev.parent, "failed to add char device %d:%d\n", MAJOR(rtc->dev.devt), rtc->id); - else + } else { dev_dbg(rtc->dev.parent, "char device (%d:%d)\n", MAJOR(rtc->dev.devt), rtc->id); + } rtc_proc_add_device(rtc); -- cgit From 24d23181e43d72ca692a479e70dfe5b0b5dd33f1 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Tue, 12 Oct 2021 12:16:29 +0800 Subject: rtc: class: check return value when calling dev_set_name() I got a null-ptr-deref report when doing fault injection test: BUG: kernel NULL pointer dereference, address: 0000000000000000 RIP: 0010:strcmp+0xc/0x20 Call Trace: __devm_rtc_register_device.cold.7+0x16a/0x2df rv3029_probe+0x4b1/0x770 [rtc_rv3029c2] rv3029_i2c_probe+0x141/0x180 [rtc_rv3029c2] i2c_device_probe+0xa07/0xbb0 really_probe+0x285/0xc30 If dev_set_name() fails, dev_name() is null, it causes null-ptr-deref, we need check the return value of dev_set_name(). Reported-by: Hulk Robot Signed-off-by: Yang Yingliang Signed-off-by: Alexandre Belloni Link: https://lore.kernel.org/r/20211012041629.2504158-1-yangyingliang@huawei.com --- drivers/rtc/class.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/rtc/class.c') diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 654e921244bf..dbccd71589b9 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -364,7 +364,9 @@ struct rtc_device *devm_rtc_allocate_device(struct device *dev) rtc->id = id; rtc->dev.parent = dev; - dev_set_name(&rtc->dev, "rtc%d", id); + err = dev_set_name(&rtc->dev, "rtc%d", id); + if (err) + return ERR_PTR(err); err = devm_add_action_or_reset(dev, devm_rtc_release_device, rtc); if (err) -- cgit From 2268551935dbf1abcbb4d4fb7b1ad74dbe0d1be0 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 18 Oct 2021 17:19:29 +0200 Subject: rtc: expose correction feature Add a new feature for RTCs able to correct the oscillator imprecision. This is also called offset or trimming. Such drivers have a .set_offset callback, use that to set the feature bit from the core. Signed-off-by: Alexandre Belloni Link: https://lore.kernel.org/r/20211018151933.76865-4-alexandre.belloni@bootlin.com --- drivers/rtc/class.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/rtc/class.c') diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index dbccd71589b9..2e0cbc190a8a 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -389,6 +389,9 @@ int __devm_rtc_register_device(struct module *owner, struct rtc_device *rtc) if (!rtc->ops->set_alarm) clear_bit(RTC_FEATURE_ALARM, rtc->features); + if (rtc->ops->set_offset) + set_bit(RTC_FEATURE_CORRECTION, rtc->features); + rtc->owner = owner; rtc_device_get_offset(rtc); -- cgit From adb17a053e460f20740d713c4843d6966e66b1b1 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 18 Oct 2021 17:23:36 +0200 Subject: rtc: expose RTC_FEATURE_UPDATE_INTERRUPT Set RTC_FEATURE_UPDATE_INTERRUPT by default and clear it when it is not supported. Signed-off-by: Alexandre Belloni Link: https://lore.kernel.org/r/20211018152337.78732-1-alexandre.belloni@bootlin.com --- drivers/rtc/class.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/rtc/class.c') diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 2e0cbc190a8a..4b460c61f1d8 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -232,6 +232,7 @@ static struct rtc_device *rtc_allocate_device(void) rtc->pie_enabled = 0; set_bit(RTC_FEATURE_ALARM, rtc->features); + set_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->features); return rtc; } @@ -389,6 +390,9 @@ int __devm_rtc_register_device(struct module *owner, struct rtc_device *rtc) if (!rtc->ops->set_alarm) clear_bit(RTC_FEATURE_ALARM, rtc->features); + if (rtc->uie_unsupported) + clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->features); + if (rtc->ops->set_offset) set_bit(RTC_FEATURE_CORRECTION, rtc->features); -- cgit