Skip to content

Commit 1c9977b

Browse files
nfrapradolinusw
authored andcommitted
pinctrl: mediatek: eint: Fix invalid pointer dereference for v1 platforms
Commit 3ef9f71 ("pinctrl: mediatek: Add EINT support for multiple addresses") introduced an access to the 'soc' field of struct mtk_pinctrl in mtk_eint_do_init() and for that an include of pinctrl-mtk-common-v2.h. However, pinctrl drivers relying on the v1 common driver include pinctrl-mtk-common.h instead, which provides another definition of struct mtk_pinctrl that does not contain an 'soc' field. Since mtk_eint_do_init() can be called both by v1 and v2 drivers, it will now try to dereference an invalid pointer when called on v1 platforms. This has been observed on Genio 350 EVK (MT8365), which crashes very early in boot (the kernel trace can only be seen with earlycon). In order to fix this, since 'struct mtk_pinctrl' was only needed to get a 'struct mtk_eint_pin', make 'struct mtk_eint_pin' a parameter of mtk_eint_do_init() so that callers need to supply it, removing mtk_eint_do_init()'s dependency on any particular 'struct mtk_pinctrl'. Fixes: 3ef9f71 ("pinctrl: mediatek: Add EINT support for multiple addresses") Suggested-by: AngeloGioacchino Del Regno <[email protected]> Signed-off-by: Nícolas F. R. A. Prado <[email protected]> Link: https://lore.kernel.org/20250520-genio-350-eint-null-ptr-deref-fix-v2-1-6a3ca966a7ba@collabora.com Signed-off-by: Linus Walleij <[email protected]>
1 parent a660d9e commit 1c9977b

File tree

4 files changed

+16
-19
lines changed

4 files changed

+16
-19
lines changed

drivers/pinctrl/mediatek/mtk-eint.c

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
#include <linux/platform_device.h>
2323

2424
#include "mtk-eint.h"
25-
#include "pinctrl-mtk-common-v2.h"
2625

2726
#define MTK_EINT_EDGE_SENSITIVE 0
2827
#define MTK_EINT_LEVEL_SENSITIVE 1
@@ -505,10 +504,9 @@ int mtk_eint_find_irq(struct mtk_eint *eint, unsigned long eint_n)
505504
}
506505
EXPORT_SYMBOL_GPL(mtk_eint_find_irq);
507506

508-
int mtk_eint_do_init(struct mtk_eint *eint)
507+
int mtk_eint_do_init(struct mtk_eint *eint, struct mtk_eint_pin *eint_pin)
509508
{
510509
unsigned int size, i, port, virq, inst = 0;
511-
struct mtk_pinctrl *hw = (struct mtk_pinctrl *)eint->pctl;
512510

513511
/* If clients don't assign a specific regs, let's use generic one */
514512
if (!eint->regs)
@@ -519,7 +517,15 @@ int mtk_eint_do_init(struct mtk_eint *eint)
519517
if (!eint->base_pin_num)
520518
return -ENOMEM;
521519

522-
if (eint->nbase == 1) {
520+
if (eint_pin) {
521+
eint->pins = eint_pin;
522+
for (i = 0; i < eint->hw->ap_num; i++) {
523+
inst = eint->pins[i].instance;
524+
if (inst >= eint->nbase)
525+
continue;
526+
eint->base_pin_num[inst]++;
527+
}
528+
} else {
523529
size = eint->hw->ap_num * sizeof(struct mtk_eint_pin);
524530
eint->pins = devm_kmalloc(eint->dev, size, GFP_KERNEL);
525531
if (!eint->pins)
@@ -533,16 +539,6 @@ int mtk_eint_do_init(struct mtk_eint *eint)
533539
}
534540
}
535541

536-
if (hw && hw->soc && hw->soc->eint_pin) {
537-
eint->pins = hw->soc->eint_pin;
538-
for (i = 0; i < eint->hw->ap_num; i++) {
539-
inst = eint->pins[i].instance;
540-
if (inst >= eint->nbase)
541-
continue;
542-
eint->base_pin_num[inst]++;
543-
}
544-
}
545-
546542
eint->pin_list = devm_kmalloc(eint->dev, eint->nbase * sizeof(u16 *), GFP_KERNEL);
547543
if (!eint->pin_list)
548544
goto err_pin_list;
@@ -610,7 +606,7 @@ int mtk_eint_do_init(struct mtk_eint *eint)
610606
err_wake_mask:
611607
devm_kfree(eint->dev, eint->pin_list);
612608
err_pin_list:
613-
if (eint->nbase == 1)
609+
if (!eint_pin)
614610
devm_kfree(eint->dev, eint->pins);
615611
err_pins:
616612
devm_kfree(eint->dev, eint->base_pin_num);

drivers/pinctrl/mediatek/mtk-eint.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,15 +88,16 @@ struct mtk_eint {
8888
};
8989

9090
#if IS_ENABLED(CONFIG_EINT_MTK)
91-
int mtk_eint_do_init(struct mtk_eint *eint);
91+
int mtk_eint_do_init(struct mtk_eint *eint, struct mtk_eint_pin *eint_pin);
9292
int mtk_eint_do_suspend(struct mtk_eint *eint);
9393
int mtk_eint_do_resume(struct mtk_eint *eint);
9494
int mtk_eint_set_debounce(struct mtk_eint *eint, unsigned long eint_n,
9595
unsigned int debounce);
9696
int mtk_eint_find_irq(struct mtk_eint *eint, unsigned long eint_n);
9797

9898
#else
99-
static inline int mtk_eint_do_init(struct mtk_eint *eint)
99+
static inline int mtk_eint_do_init(struct mtk_eint *eint,
100+
struct mtk_eint_pin *eint_pin)
100101
{
101102
return -EOPNOTSUPP;
102103
}

drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ int mtk_build_eint(struct mtk_pinctrl *hw, struct platform_device *pdev)
419419
hw->eint->pctl = hw;
420420
hw->eint->gpio_xlate = &mtk_eint_xt;
421421

422-
ret = mtk_eint_do_init(hw->eint);
422+
ret = mtk_eint_do_init(hw->eint, hw->soc->eint_pin);
423423
if (ret)
424424
goto err_free_eint;
425425

drivers/pinctrl/mediatek/pinctrl-mtk-common.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1038,7 +1038,7 @@ static int mtk_eint_init(struct mtk_pinctrl *pctl, struct platform_device *pdev)
10381038
pctl->eint->pctl = pctl;
10391039
pctl->eint->gpio_xlate = &mtk_eint_xt;
10401040

1041-
return mtk_eint_do_init(pctl->eint);
1041+
return mtk_eint_do_init(pctl->eint, NULL);
10421042
}
10431043

10441044
/* This is used as a common probe function */

0 commit comments

Comments
 (0)