]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
pinctrl: mediatek: make devm allocations safer and clearer in mtk_eint_do_init()
authorLiang Jie <liangjie@lixiang.com>
Tue, 9 Dec 2025 10:02:17 +0000 (18:02 +0800)
committerLinus Walleij <linusw@kernel.org>
Fri, 26 Dec 2025 18:13:01 +0000 (19:13 +0100)
mtk_eint_do_init() allocates several pointer arrays which are then
populated in a per-instance loop and freed on error. The arrays are
currently allocated with devm_kmalloc(), so their entries are left
uninitialised until the per-instance allocations succeed.

On a failure in the middle of the loop, the error path iterates over
the full nbase range and calls devm_kfree() on each element. For
indices which were never initialised, the corresponding array entries
contain stack garbage. If any of those happen to be non-zero,
devm_kfree() will pass them to devres_destroy(), which will WARN
because there is no matching devm_kmalloc() resource for such bogus
pointers.

Improve the robustness and readability by:

  - Using devm_kcalloc() for the pointer arrays so that all entries
    start as NULL, ensuring that only genuinely initialised elements
    may be freed and preventing spurious WARN_ON()s in the error path.
  - Switching the allocations to sizeof(*ptr) / sizeof(**ptr) forms,
    avoiding hard-coded element types and making the code more resilient
    to future type changes.
  - Dropping the redundant NULL checks before devm_kfree(), as
    devm_kfree() safely handles NULL pointers.

The functional behaviour in the successful initialisation path remains
unchanged, while the error handling becomes simpler and less
error-prone.

Reviewed-by: fanggeng <fanggeng@lixiang.com>
Signed-off-by: Liang Jie <liangjie@lixiang.com>
Signed-off-by: Linus Walleij <linusw@kernel.org>
drivers/pinctrl/mediatek/mtk-eint.c

index c8c5097c11c4d14eb41bdd7f9cb93b4a5756d2b2..2a3c04eedc5f384f8ec15c759f8ee84300fe5d0c 100644 (file)
@@ -544,24 +544,32 @@ int mtk_eint_do_init(struct mtk_eint *eint, struct mtk_eint_pin *eint_pin)
                }
        }
 
-       eint->pin_list = devm_kmalloc(eint->dev, eint->nbase * sizeof(u16 *), GFP_KERNEL);
+       eint->pin_list = devm_kcalloc(eint->dev, eint->nbase,
+                                     sizeof(*eint->pin_list), GFP_KERNEL);
        if (!eint->pin_list)
                goto err_pin_list;
 
-       eint->wake_mask = devm_kmalloc(eint->dev, eint->nbase * sizeof(u32 *), GFP_KERNEL);
+       eint->wake_mask = devm_kcalloc(eint->dev, eint->nbase,
+                                      sizeof(*eint->wake_mask), GFP_KERNEL);
        if (!eint->wake_mask)
                goto err_wake_mask;
 
-       eint->cur_mask = devm_kmalloc(eint->dev, eint->nbase * sizeof(u32 *), GFP_KERNEL);
+       eint->cur_mask = devm_kcalloc(eint->dev, eint->nbase,
+                                     sizeof(*eint->cur_mask), GFP_KERNEL);
        if (!eint->cur_mask)
                goto err_cur_mask;
 
        for (i = 0; i < eint->nbase; i++) {
-               eint->pin_list[i] = devm_kzalloc(eint->dev, eint->base_pin_num[i] * sizeof(u16),
+               eint->pin_list[i] = devm_kzalloc(eint->dev,
+                                                eint->base_pin_num[i] * sizeof(**eint->pin_list),
                                                 GFP_KERNEL);
                port = DIV_ROUND_UP(eint->base_pin_num[i], 32);
-               eint->wake_mask[i] = devm_kzalloc(eint->dev, port * sizeof(u32), GFP_KERNEL);
-               eint->cur_mask[i] = devm_kzalloc(eint->dev, port * sizeof(u32), GFP_KERNEL);
+               eint->wake_mask[i] = devm_kzalloc(eint->dev,
+                                                 port * sizeof(**eint->wake_mask),
+                                                 GFP_KERNEL);
+               eint->cur_mask[i] = devm_kzalloc(eint->dev,
+                                                port * sizeof(**eint->cur_mask),
+                                                GFP_KERNEL);
                if (!eint->pin_list[i] || !eint->wake_mask[i] || !eint->cur_mask[i])
                        goto err_eint;
        }
@@ -597,12 +605,9 @@ int mtk_eint_do_init(struct mtk_eint *eint, struct mtk_eint_pin *eint_pin)
 
 err_eint:
        for (i = 0; i < eint->nbase; i++) {
-               if (eint->cur_mask[i])
-                       devm_kfree(eint->dev, eint->cur_mask[i]);
-               if (eint->wake_mask[i])
-                       devm_kfree(eint->dev, eint->wake_mask[i]);
-               if (eint->pin_list[i])
-                       devm_kfree(eint->dev, eint->pin_list[i]);
+               devm_kfree(eint->dev, eint->cur_mask[i]);
+               devm_kfree(eint->dev, eint->wake_mask[i]);
+               devm_kfree(eint->dev, eint->pin_list[i]);
        }
        devm_kfree(eint->dev, eint->cur_mask);
 err_cur_mask: