mfd: menelaus: Fix possible race condition and leak
The IRQ work is added 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 calling menelaus_add_irq_work. Also, this solves a possible leak as the RTC is never released. Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com> Signed-off-by: Lee Jones <lee.jones@linaro.org>
This commit is contained in:
Родитель
5b394b2ddf
Коммит
9612f8f503
|
@ -1094,6 +1094,7 @@ static void menelaus_rtc_alarm_work(struct menelaus_chip *m)
|
|||
static inline void menelaus_rtc_init(struct menelaus_chip *m)
|
||||
{
|
||||
int alarm = (m->client->irq > 0);
|
||||
int err;
|
||||
|
||||
/* assume 32KDETEN pin is pulled high */
|
||||
if (!(menelaus_read_reg(MENELAUS_OSC_CTRL) & 0x80)) {
|
||||
|
@ -1101,6 +1102,12 @@ static inline void menelaus_rtc_init(struct menelaus_chip *m)
|
|||
return;
|
||||
}
|
||||
|
||||
m->rtc = devm_rtc_allocate_device(&m->client->dev);
|
||||
if (IS_ERR(m->rtc))
|
||||
return;
|
||||
|
||||
m->rtc->ops = &menelaus_rtc_ops;
|
||||
|
||||
/* support RTC alarm; it can issue wakeups */
|
||||
if (alarm) {
|
||||
if (menelaus_add_irq_work(MENELAUS_RTCALM_IRQ,
|
||||
|
@ -1125,10 +1132,8 @@ static inline void menelaus_rtc_init(struct menelaus_chip *m)
|
|||
menelaus_write_reg(MENELAUS_RTC_CTRL, m->rtc_control);
|
||||
}
|
||||
|
||||
m->rtc = rtc_device_register(DRIVER_NAME,
|
||||
&m->client->dev,
|
||||
&menelaus_rtc_ops, THIS_MODULE);
|
||||
if (IS_ERR(m->rtc)) {
|
||||
err = rtc_register_device(m->rtc);
|
||||
if (err) {
|
||||
if (alarm) {
|
||||
menelaus_remove_irq_work(MENELAUS_RTCALM_IRQ);
|
||||
device_init_wakeup(&m->client->dev, 0);
|
||||
|
|
Загрузка…
Ссылка в новой задаче