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 <hulkci@huawei.com> Signed-off-by: Yang Yingliang <yangyingliang@huawei.com> Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com> Link: https://lore.kernel.org/r/20211011132114.3663509-1-yangyingliang@huawei.com
This commit is contained in:
parent
7caadcfa8a
commit
789c1093f0
|
@ -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);
|
||||
|
||||
|
|
|
@ -80,6 +80,7 @@ struct rtc_timer {
|
|||
|
||||
/* flags */
|
||||
#define RTC_DEV_BUSY 0
|
||||
#define RTC_NO_CDEV 1
|
||||
|
||||
struct rtc_device {
|
||||
struct device dev;
|
||||
|
|
Loading…
Reference in New Issue