rtc: cmos: take rtc_lock while reading from CMOS
authorMateusz Jończyk <mat.jonczyk@o2.pl>
Fri, 10 Dec 2021 20:01:23 +0000 (21:01 +0100)
committerAlexandre Belloni <alexandre.belloni@bootlin.com>
Thu, 16 Dec 2021 20:50:06 +0000 (21:50 +0100)
Reading from the CMOS involves writing to the index register and then
reading from the data register. Therefore access to the CMOS has to be
serialized with rtc_lock. This invocation of CMOS_READ was not
serialized, which could cause trouble when other code is accessing CMOS
at the same time.

Use spin_lock_irq() like the rest of the function.

Nothing in kernel modifies the RTC_DM_BINARY bit, so there could be a
separate pair of spin_lock_irq() / spin_unlock_irq() before doing the
math.

Signed-off-by: Mateusz Jończyk <mat.jonczyk@o2.pl>
Reviewed-by: Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>
Cc: stable@vger.kernel.org
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Link: https://lore.kernel.org/r/20211210200131.153887-2-mat.jonczyk@o2.pl
drivers/rtc/rtc-cmos.c

index 4eb53412b8085e12d668c2aef3b215b939094143..dc3f8b0dde9891886e87b2e4e6a1735b1c10baad 100644 (file)
@@ -457,7 +457,10 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
        min = t->time.tm_min;
        sec = t->time.tm_sec;
 
+       spin_lock_irq(&rtc_lock);
        rtc_control = CMOS_READ(RTC_CONTROL);
+       spin_unlock_irq(&rtc_lock);
+
        if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
                /* Writing 0xff means "don't care" or "match all".  */
                mon = (mon <= 12) ? bin2bcd(mon) : 0xff;