* [PATCH] serial: 8250: fix use-after-free of IRQ action name on port removal
@ 2026-11-03 23:41 ` Joas Antonio dos Santos via B4 Relay
0 siblings, 0 replies; 3+ messages in thread
From: Joas Antonio dos Santos @ 2026-11-03 23:41 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby
Cc: linux-kernel, linux-serial, stable, syzbot+bc6b37960b1d13f68f9f,
Joas Antonio dos Santos
serial_link_irq_chain() passes up->port.name directly to request_irq().
The IRQ subsystem stores this pointer in irqaction->name without copying
the string.
When the port that originally called request_irq() is removed while
other ports still share the same IRQ:
1. serial_unlink_irq_chain() removes the port from the shared list
2. Since other ports remain, free_irq() is NOT called
3. irqaction->name still references the removed port's name string
4. serial_core_remove_one_port() frees uport->name (kfree at line 3292)
5. irqaction->name becomes a dangling pointer
Any subsequent read of /proc/interrupts dereferences the freed string
via show_interrupts() -> seq_printf("%s", action->name), triggering a
KASAN slab-use-after-free on the freed kmalloc-8 object.
Fix by giving struct irq_info ownership of the name string passed to
request_irq(). serial_get_or_create_irq_info() now kstrdup()s the port
name into irq_info->name when creating a new irq_info, and
serial_do_unlink() frees it alongside the irq_info. This decouples the
IRQ action name lifetime from any individual port's lifetime.
Found by LLM-assisted code review of syzbot-reported crash patterns.
Reported-by: syzbot+bc6b37960b1d13f68f9f@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=bc6b37960b1d13f68f9f
Fixes: f7048b15900f ("tty: serial_core: Add name field to uart_port struct")
Cc: stable@vger.kernel.org
Signed-off-by: Joas Antonio dos Santos <joasantonio108@gmail.com>
---
serial_link_irq_chain() passes up->port.name directly to request_irq().
When the first port sharing an IRQ is removed, kfree(uport->name) frees
the string while irqaction->name still references it. Reading
/proc/interrupts then triggers a KASAN slab-use-after-free.
syzbot link: https://syzkaller.appspot.com/bug?extid=bc6b37960b1d13f68f9f
---
drivers/tty/serial/8250/8250_core.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 42319843c..f73113daa 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -47,6 +47,7 @@ struct irq_info {
int irq;
spinlock_t lock; /* Protects list not the hash */
struct list_head *head;
+ const char *name; /* owned copy for request_irq() */
};
#define IRQ_HASH_BITS 5 /* Can be adjusted later */
@@ -122,6 +123,7 @@ static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up)
/* List empty so throw away the hash node */
if (i->head == NULL) {
hlist_del(&i->node);
+ kfree(i->name);
kfree(i);
}
}
@@ -145,6 +147,12 @@ static struct irq_info *serial_get_or_create_irq_info(const struct uart_8250_por
if (i == NULL)
return ERR_PTR(-ENOMEM);
+ i->name = kstrdup(up->port.name, GFP_KERNEL);
+ if (!i->name) {
+ kfree(i);
+ return ERR_PTR(-ENOMEM);
+ }
+
spin_lock_init(&i->lock);
i->irq = up->port.irq;
hash_add(irq_lists, &i->node, i->irq);
@@ -172,7 +180,7 @@ static int serial_link_irq_chain(struct uart_8250_port *up)
i->head = &up->list;
}
- ret = request_irq(up->port.irq, serial8250_interrupt, up->port.irqflags, up->port.name, i);
+ ret = request_irq(up->port.irq, serial8250_interrupt, up->port.irqflags, i->name, i);
if (ret < 0)
serial_do_unlink(i, up);
---
base-commit: 05441d697f7f9a927264f4058cbbc6a03dfcac9d
change-id: 20261103-serial-8250-irq-uaf-0d03f8a48a98
Best regards,
--
Joas Antonio dos Santos <joasantonio108@gmail.com>
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH] serial: 8250: fix use-after-free of IRQ action name on port removal
@ 2026-11-03 23:41 ` Joas Antonio dos Santos via B4 Relay
0 siblings, 0 replies; 3+ messages in thread
From: Joas Antonio dos Santos via B4 Relay @ 2026-11-03 23:41 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby
Cc: linux-kernel, linux-serial, stable, syzbot+bc6b37960b1d13f68f9f,
Joas Antonio dos Santos
From: Joas Antonio dos Santos <joasantonio108@gmail.com>
serial_link_irq_chain() passes up->port.name directly to request_irq().
The IRQ subsystem stores this pointer in irqaction->name without copying
the string.
When the port that originally called request_irq() is removed while
other ports still share the same IRQ:
1. serial_unlink_irq_chain() removes the port from the shared list
2. Since other ports remain, free_irq() is NOT called
3. irqaction->name still references the removed port's name string
4. serial_core_remove_one_port() frees uport->name (kfree at line 3292)
5. irqaction->name becomes a dangling pointer
Any subsequent read of /proc/interrupts dereferences the freed string
via show_interrupts() -> seq_printf("%s", action->name), triggering a
KASAN slab-use-after-free on the freed kmalloc-8 object.
Fix by giving struct irq_info ownership of the name string passed to
request_irq(). serial_get_or_create_irq_info() now kstrdup()s the port
name into irq_info->name when creating a new irq_info, and
serial_do_unlink() frees it alongside the irq_info. This decouples the
IRQ action name lifetime from any individual port's lifetime.
Found by LLM-assisted code review of syzbot-reported crash patterns.
Reported-by: syzbot+bc6b37960b1d13f68f9f@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=bc6b37960b1d13f68f9f
Fixes: f7048b15900f ("tty: serial_core: Add name field to uart_port struct")
Cc: stable@vger.kernel.org
Signed-off-by: Joas Antonio dos Santos <joasantonio108@gmail.com>
---
serial_link_irq_chain() passes up->port.name directly to request_irq().
When the first port sharing an IRQ is removed, kfree(uport->name) frees
the string while irqaction->name still references it. Reading
/proc/interrupts then triggers a KASAN slab-use-after-free.
syzbot link: https://syzkaller.appspot.com/bug?extid=bc6b37960b1d13f68f9f
---
drivers/tty/serial/8250/8250_core.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 42319843c..f73113daa 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -47,6 +47,7 @@ struct irq_info {
int irq;
spinlock_t lock; /* Protects list not the hash */
struct list_head *head;
+ const char *name; /* owned copy for request_irq() */
};
#define IRQ_HASH_BITS 5 /* Can be adjusted later */
@@ -122,6 +123,7 @@ static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up)
/* List empty so throw away the hash node */
if (i->head == NULL) {
hlist_del(&i->node);
+ kfree(i->name);
kfree(i);
}
}
@@ -145,6 +147,12 @@ static struct irq_info *serial_get_or_create_irq_info(const struct uart_8250_por
if (i == NULL)
return ERR_PTR(-ENOMEM);
+ i->name = kstrdup(up->port.name, GFP_KERNEL);
+ if (!i->name) {
+ kfree(i);
+ return ERR_PTR(-ENOMEM);
+ }
+
spin_lock_init(&i->lock);
i->irq = up->port.irq;
hash_add(irq_lists, &i->node, i->irq);
@@ -172,7 +180,7 @@ static int serial_link_irq_chain(struct uart_8250_port *up)
i->head = &up->list;
}
- ret = request_irq(up->port.irq, serial8250_interrupt, up->port.irqflags, up->port.name, i);
+ ret = request_irq(up->port.irq, serial8250_interrupt, up->port.irqflags, i->name, i);
if (ret < 0)
serial_do_unlink(i, up);
---
base-commit: 05441d697f7f9a927264f4058cbbc6a03dfcac9d
change-id: 20261103-serial-8250-irq-uaf-0d03f8a48a98
Best regards,
--
Joas Antonio dos Santos <joasantonio108@gmail.com>
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] serial: 8250: fix use-after-free of IRQ action name on port removal
2026-11-03 23:41 ` Joas Antonio dos Santos via B4 Relay
(?)
@ 2026-11-03 23:50 ` sashiko-bot
-1 siblings, 0 replies; 3+ messages in thread
From: sashiko-bot @ 2026-11-03 23:50 UTC (permalink / raw)
To: Joas Antonio dos Santos; +Cc: linux-serial
> From: Joas Antonio dos Santos <joasantonio108@gmail.com>
>
> serial_link_irq_chain() passes up->port.name directly to request_irq().
> The IRQ subsystem stores this pointer in irqaction->name without copying
> the string.
>
> When the port that originally called request_irq() is removed while
> other ports still share the same IRQ:
>
> 1. serial_unlink_irq_chain() removes the port from the shared list
> 2. Since other ports remain, free_irq() is NOT called
> 3. irqaction->name still references the removed port's name string
> 4. serial_core_remove_one_port() frees uport->name (kfree at line 3292)
> 5. irqaction->name becomes a dangling pointer
>
> [ ... ]
> Reported-by: syzbot+bc6b37960b1d13f68f9f@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=bc6b37960b1d13f68f9f
> Fixes: f7048b15900f ("tty: serial_core: Add name field to uart_port struct")
> Cc: stable@vger.kernel.org
> Signed-off-by: Joas Antonio dos Santos <joasantonio108@gmail.com>
Sashiko has reviewed this patch and found no issues.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261103-serial-8250-irq-uaf-v1-1-24223dcc3119@gmail.com?part=1
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-11-03 23:50 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-03 23:41 [PATCH] serial: 8250: fix use-after-free of IRQ action name on port removal Joas Antonio dos Santos
2026-11-03 23:41 ` Joas Antonio dos Santos via B4 Relay
2026-11-03 23:50 ` sashiko-bot
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.