From: Yu Liao liaoyu15@huawei.com
hulk inclusion category: bugfix bugzilla: 186781, https://gitee.com/openeuler/kernel/issues/I61CEW CVE: NA
--------------------------------
Split out a function that does not acquire ops_lock from rtc_update_irq_enable, in preparation for fixing RTC_RD_TIME and RTC_UIE_ON race problem.
Signed-off-by: Yu Liao liaoyu15@huawei.com Reviewed-by: Wei Li liwei391@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/rtc/interface.c | 34 ++++++++++++++++++++-------------- include/linux/rtc.h | 1 + 2 files changed, 21 insertions(+), 14 deletions(-)
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 146056858135..d4e576a65885 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -543,20 +543,10 @@ int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled) } EXPORT_SYMBOL_GPL(rtc_alarm_irq_enable);
-int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled) +int __rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled) { - int rc = 0, err; + int rc = 0, err = 0;
- err = mutex_lock_interruptible(&rtc->ops_lock); - if (err) - return err; - -#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL - if (enabled == 0 && rtc->uie_irq_active) { - mutex_unlock(&rtc->ops_lock); - return rtc_dev_update_irq_enable_emul(rtc, 0); - } -#endif /* make sure we're changing state */ if (rtc->uie_rtctimer.enabled == enabled) goto out; @@ -583,8 +573,6 @@ int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled) }
out: - mutex_unlock(&rtc->ops_lock); - /* * __rtc_read_time() failed, this probably means that the RTC time has * never been set or less probably there is a transient error on the @@ -594,6 +582,24 @@ int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled) if (rc) return rc;
+ return err; +} + +int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled) +{ + int err; + +#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL + if (enabled == 0 && rtc->uie_irq_active) + return rtc_dev_update_irq_enable_emul(rtc, 0); +#endif + + err = mutex_lock_interruptible(&rtc->ops_lock); + if (err) + return err; + err = __rtc_update_irq_enable(rtc, enabled); + mutex_unlock(&rtc->ops_lock); + #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL /* * Enable emulation if the driver returned -EINVAL to signal that it has diff --git a/include/linux/rtc.h b/include/linux/rtc.h index 22d1575e4991..d0cd0a611ad3 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h @@ -182,6 +182,7 @@ extern void rtc_class_close(struct rtc_device *rtc); extern int rtc_irq_set_state(struct rtc_device *rtc, int enabled); extern int rtc_irq_set_freq(struct rtc_device *rtc, int freq); extern int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled); +extern int __rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled); extern int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled); extern int rtc_dev_update_irq_enable_emul(struct rtc_device *rtc, unsigned int enabled);