Skip to contentSkip to conversation

serial: caif: hold tty->link reference to avoid UAF in pty_write_room

PATCH Superseded Shuangpeng Bai 2 participants 4 messages Feb 26 – Mar 1

Subsystems (2)

v3 of 5 Superseded Latest is v5 →

lore
Share & tools
lore
#0 lore raw

v3 cover serial: caif: hold tty->link reference to avoid UAF in pty_write_room

Follow-up to the v2 discussion: further debugging shows the KASAN slab-use-after-free is triggered in pty_write_room(), and the faulting access is on tty->link->port.

The report points to the peer access in pty_write_room():

    tty_buffer_space_avail(tty->link->port);

This patch holds an extra kref on tty->link for the lifetime of the caif_serial line discipline: get the reference in ldisc_open() and drop it in ser_release(), and also drop it on the ldisc_open() error path.

Changes since v2:
- Update the analysis: the observed UAF is on tty->link, not ser->tty.
- Keep tty->link alive while the line discipline is active.

Shuangpeng Bai (1):
serial: caif: hold tty->link reference in ldisc_open and ser_release

 drivers/net/caif/caif_serial.c | 3 +++
 1 file changed, 3 insertions(+)
Signature · 1 line
2.34.1
#1 lore raw

PATCH v3 1/1 serial: caif: hold tty->link reference in ldisc_open and ser_release

A reproducer triggers a KASAN slab-use-after-free in pty_write_room() when caif_serial's TX path calls tty_write_room(). The faulting access is on tty->link->port.

Hold an extra kref on tty->link for the lifetime of the caif_serial line
discipline: get it in ldisc_open() and drop it in ser_release(), and also drop it on the ldisc_open() error path.

With this change applied, the reproducer no longer triggers the UAF in my testing.

This issue becomes reproducible on top of 308e7e4d0a84. Before that, the reproducer typically hits another bug first, so this UAF is not observable there.

---
 drivers/net/caif/caif_serial.c | 3 +++
 1 file changed, 3 insertions(+)
drivers/net/caif/caif_serial.c +3 -0
index b90890030751..1873d8287bb9 100644
@@ -297,6 +297,7 @@ static void ser_release(struct work_struct *work)
 			dev_close(ser->dev);
 			unregister_netdevice(ser->dev);
 			debugfs_deinit(ser);
+			tty_kref_put(tty->link);
 			tty_kref_put(tty);
 		}
 		rtnl_unlock();
@@ -331,6 +332,7 @@ static int ldisc_open(struct tty_struct *tty)
 
 	ser = netdev_priv(dev);
 	ser->tty = tty_kref_get(tty);
+	tty_kref_get(tty->link);
 	ser->dev = dev;
 	debugfs_init(ser, tty);
 	tty->receive_room = 4096;
@@ -339,6 +341,7 @@ static int ldisc_open(struct tty_struct *tty)
 	rtnl_lock();
 	result = register_netdevice(dev);
 	if (result) {
+		tty_kref_put(tty->link);
 		tty_kref_put(tty);
 		rtnl_unlock();
 		free_netdev(dev);
Signature · 1 line
2.34.1
maintainer
#2 lore raw

Re: [PATCH net v3 1/1] serial: caif: hold tty->link reference in ldisc_open and ser_release

Quoted 1 line · On Wed, 25 Feb 2026 20:36:42 -0500 Shuangpeng Bai wrote:
Fixes 308e7e4d0a84 ("serial: caif: fix use-after-free in caif_serial ldisc_close()")

Please repost and make sure you CC everyone who has given tags to this commit. The get_maintainers script will point them out to you.

And there's no need for a cover letter on a single patch submission, just add the extra info under the --- marker in the patch

Also [email protected] is not a real address, horms@

Signature · 1 line
pw-bot: cr
#3 lore raw

Re: [PATCH net v3 1/1] serial: caif: hold tty->link reference in ldisc_open and ser_release

Hi Jakub,

Thanks for the guidance. I've reposted as v4 without a cover letter and CC'd everyone pointed out by get_maintainer.pl, including the taggers of the Fixes commit. I also fixed the [email protected] address.

Thanks,
Shuangpeng