Sometimes ksz_irq_free() can be called on uninitialized ksz_irq (for
example when ksz_ptp_irq_setup() fails). It leads to freeing
uninitialized IRQ numbers and/or domains.
Ensure that IRQ numbers or domains aren't null before freeing them.
In our case the IRQ number of an initialized ksz_irq is never 0. Indeed,
it's either the device's IRQ number and we enter the IRQ setup only when
this dev->irq is strictly positive, or a virtual IRQ assigned with
irq_create_mapping() which returns strictly positive IRQ numbers.
Fixes: cc13ab18b201 ("net: dsa: microchip: ptp: enable interrupt for timestamping")
Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
--
Regarding the Fixes tag here, IMO before cc13ab18b201 it was safe to
not check the domain and the IRQ number because I don't see any path
where ksz_irq_free() would be called on a non-initialized ksz_irq
---
drivers/net/dsa/microchip/ksz_common.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 3a4516d32aa5f99109853ed400e64f8f7e2d8016..c5f8821a3a0ab7b50ddc31cc0a2f28220fe57c84 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -2858,14 +2858,17 @@ static void ksz_irq_free(struct ksz_irq *kirq)
{
int irq, virq;
- free_irq(kirq->irq_num, kirq);
+ if (kirq->irq_num)
+ free_irq(kirq->irq_num, kirq);
- for (irq = 0; irq < kirq->nirqs; irq++) {
- virq = irq_find_mapping(kirq->domain, irq);
- irq_dispose_mapping(virq);
- }
+ if (kirq->domain) {
+ for (irq = 0; irq < kirq->nirqs; irq++) {
+ virq = irq_find_mapping(kirq->domain, irq);
+ irq_dispose_mapping(virq);
+ }
- irq_domain_remove(kirq->domain);
+ irq_domain_remove(kirq->domain);
+ }
}
static irqreturn_t ksz_irq_thread_fn(int irq, void *dev_id)
--
2.51.1
On Fri, Nov 14, 2025 at 08:20:22AM +0100, Bastien Curutchet (Schneider Electric) wrote:
> Sometimes ksz_irq_free() can be called on uninitialized ksz_irq (for
> example when ksz_ptp_irq_setup() fails). It leads to freeing
> uninitialized IRQ numbers and/or domains.
>
> Ensure that IRQ numbers or domains aren't null before freeing them.
> In our case the IRQ number of an initialized ksz_irq is never 0. Indeed,
> it's either the device's IRQ number and we enter the IRQ setup only when
> this dev->irq is strictly positive, or a virtual IRQ assigned with
> irq_create_mapping() which returns strictly positive IRQ numbers.
>
> Fixes: cc13ab18b201 ("net: dsa: microchip: ptp: enable interrupt for timestamping")
> Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
> --
> Regarding the Fixes tag here, IMO before cc13ab18b201 it was safe to
> not check the domain and the IRQ number because I don't see any path
> where ksz_irq_free() would be called on a non-initialized ksz_irq
I would say the caller is wrong, not ksz_irq_free().
Functions like this come in pairs: ksz_irq_setup() & ksz_irq_free().
_free() should not be called if _setup() was not successful.
Please take a look if you can fix the caller. If the change is big,
maybe we need this as a minimal fix for net, but make the bigger
change in net-next?
Thanks
Andrew
Hi Andrew,
On 11/14/25 4:00 PM, Andrew Lunn wrote:
> On Fri, Nov 14, 2025 at 08:20:22AM +0100, Bastien Curutchet (Schneider Electric) wrote:
>> Sometimes ksz_irq_free() can be called on uninitialized ksz_irq (for
>> example when ksz_ptp_irq_setup() fails). It leads to freeing
>> uninitialized IRQ numbers and/or domains.
>>
>> Ensure that IRQ numbers or domains aren't null before freeing them.
>> In our case the IRQ number of an initialized ksz_irq is never 0. Indeed,
>> it's either the device's IRQ number and we enter the IRQ setup only when
>> this dev->irq is strictly positive, or a virtual IRQ assigned with
>> irq_create_mapping() which returns strictly positive IRQ numbers.
>>
>> Fixes: cc13ab18b201 ("net: dsa: microchip: ptp: enable interrupt for timestamping")
>> Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
>> --
>> Regarding the Fixes tag here, IMO before cc13ab18b201 it was safe to
>> not check the domain and the IRQ number because I don't see any path
>> where ksz_irq_free() would be called on a non-initialized ksz_irq
>
> I would say the caller is wrong, not ksz_irq_free().
>
> Functions like this come in pairs: ksz_irq_setup() & ksz_irq_free().
> _free() should not be called if _setup() was not successful.
>
> Please take a look if you can fix the caller. If the change is big,
> maybe we need this as a minimal fix for net, but make the bigger
> change in net-next?
Ok, I'll look at it, I think the change won't be that big.
Best regards,
Bastien
© 2016 - 2026 Red Hat, Inc.