Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

pinctrl: mediatek: make devm allocations safer and clearer in mtk_eint_do_init()

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>

authored by

Liang Jie and committed by
Linus Walleij
255b721c a035b23b

+17 -12
+17 -12
drivers/pinctrl/mediatek/mtk-eint.c
··· 544 544 } 545 545 } 546 546 547 - eint->pin_list = devm_kmalloc(eint->dev, eint->nbase * sizeof(u16 *), GFP_KERNEL); 547 + eint->pin_list = devm_kcalloc(eint->dev, eint->nbase, 548 + sizeof(*eint->pin_list), GFP_KERNEL); 548 549 if (!eint->pin_list) 549 550 goto err_pin_list; 550 551 551 - eint->wake_mask = devm_kmalloc(eint->dev, eint->nbase * sizeof(u32 *), GFP_KERNEL); 552 + eint->wake_mask = devm_kcalloc(eint->dev, eint->nbase, 553 + sizeof(*eint->wake_mask), GFP_KERNEL); 552 554 if (!eint->wake_mask) 553 555 goto err_wake_mask; 554 556 555 - eint->cur_mask = devm_kmalloc(eint->dev, eint->nbase * sizeof(u32 *), GFP_KERNEL); 557 + eint->cur_mask = devm_kcalloc(eint->dev, eint->nbase, 558 + sizeof(*eint->cur_mask), GFP_KERNEL); 556 559 if (!eint->cur_mask) 557 560 goto err_cur_mask; 558 561 559 562 for (i = 0; i < eint->nbase; i++) { 560 - eint->pin_list[i] = devm_kzalloc(eint->dev, eint->base_pin_num[i] * sizeof(u16), 563 + eint->pin_list[i] = devm_kzalloc(eint->dev, 564 + eint->base_pin_num[i] * sizeof(**eint->pin_list), 561 565 GFP_KERNEL); 562 566 port = DIV_ROUND_UP(eint->base_pin_num[i], 32); 563 - eint->wake_mask[i] = devm_kzalloc(eint->dev, port * sizeof(u32), GFP_KERNEL); 564 - eint->cur_mask[i] = devm_kzalloc(eint->dev, port * sizeof(u32), GFP_KERNEL); 567 + eint->wake_mask[i] = devm_kzalloc(eint->dev, 568 + port * sizeof(**eint->wake_mask), 569 + GFP_KERNEL); 570 + eint->cur_mask[i] = devm_kzalloc(eint->dev, 571 + port * sizeof(**eint->cur_mask), 572 + GFP_KERNEL); 565 573 if (!eint->pin_list[i] || !eint->wake_mask[i] || !eint->cur_mask[i]) 566 574 goto err_eint; 567 575 } ··· 605 597 606 598 err_eint: 607 599 for (i = 0; i < eint->nbase; i++) { 608 - if (eint->cur_mask[i]) 609 - devm_kfree(eint->dev, eint->cur_mask[i]); 610 - if (eint->wake_mask[i]) 611 - devm_kfree(eint->dev, eint->wake_mask[i]); 612 - if (eint->pin_list[i]) 613 - devm_kfree(eint->dev, eint->pin_list[i]); 600 + devm_kfree(eint->dev, eint->cur_mask[i]); 601 + devm_kfree(eint->dev, eint->wake_mask[i]); 602 + devm_kfree(eint->dev, eint->pin_list[i]); 614 603 } 615 604 devm_kfree(eint->dev, eint->cur_mask); 616 605 err_cur_mask: