[tip: timers/clocksource] clocksource/drivers/nxp-pit: Fix IRQ leak on cpuhp_setup_state error path

From: tip-bot2 for WenTao Liang

Date: Mon Aug 17 2026 - 04:38:29 EST


The following commit has been merged into the timers/clocksource branch of tip:

Commit-ID: 05520e035f8332c8e33f3011b5ca016fde61793d
Gitweb: https://git.kernel.org/tip/05520e035f8332c8e33f3011b5ca016fde61793d
Author: WenTao Liang <vulab@xxxxxxxxxxx>
AuthorDate: Sun, 28 Jun 2026 21:07:00 +08:00
Committer: Daniel Lezcano <daniel.lezcano@xxxxxxxxxx>
CommitterDate: Thu, 13 Aug 2026 18:13:01 +02:00

clocksource/drivers/nxp-pit: Fix IRQ leak on cpuhp_setup_state error path

When cpuhp_setup_state fails after pit_clockevent_per_cpu_init has
successfully called request_irq, the error handling jumps directly to
out_pit_clocksource_unregister without freeing the registered IRQ.

This leaks the IRQ line and, since kfree(pit) follows, leaves a
dangling pointer registered as the interrupt handler's dev_id,
potentially leading to a use-after-free if the IRQ fires afterwards.

Fix it by calling pit_clockevent_per_cpu_exit to properly release the
IRQ before falling through to the existing cleanup chain.

Suggested-by: Greg KH <gregkh@xxxxxxxxxxxxxxxxxxx>
Fixes: bee33f22d7c3 ("clocksource/drivers/nxp-pit: Add NXP Automotive s32g2 / s32g3 support")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: WenTao Liang <vulab@xxxxxxxxxxx>
Signed-off-by: Daniel Lezcano <daniel.lezcano@xxxxxxxxxx>
Link: https://patch.msgid.link/20260628130700.45680-1-vulab@xxxxxxxxxxx
---
drivers/clocksource/timer-nxp-pit.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/clocksource/timer-nxp-pit.c b/drivers/clocksource/timer-nxp-pit.c
index bc5157e..2f70d1d 100644
--- a/drivers/clocksource/timer-nxp-pit.c
+++ b/drivers/clocksource/timer-nxp-pit.c
@@ -328,8 +328,10 @@ static int pit_timer_init(struct device_node *np)
if (pit_instances == max_pit_instances) {
ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "PIT timer:starting",
pit_clockevent_starting_cpu, NULL);
- if (ret < 0)
+ if (ret < 0) {
+ pit_clockevent_per_cpu_exit(pit, pit_instances);
goto out_pit_clocksource_unregister;
+ }
}

return 0;