Re: [PATCH net v2 1/1] serial: caif: fix remaining ser->tty UAF in TX path

From: Shuangpeng

Date: Sun Feb 15 2026 - 14:22:34 EST



> On Feb 15, 2026, at 03:55, Hillf Danton <hdanton@xxxxxxxx> wrote:
>
> On Sat, 14 Feb 2026 21:51:41 -0500 Shuangpeng Bai wrote:
>> A reproducer exposes a KASAN use-after-free in caif_serial's TX path
>> (e.g., via tty_write_room() / tty->ops->write()) on top of commit
>> <308e7e4d0a84> ("serial: caif: fix use-after-free in caif_serial
>> ldisc_close()").
>>
>> That commit moved tty_kref_put() to ser_release(). There is still a race
>> because the TX path may fetch ser->tty and use it while ser_release()
>> drops the last tty reference:
>>
>> CPU 0 (ser_release worker) CPU 1 (xmit)
>> ------------------------- ------------
>> caif_xmit()
>> handle_tx()
>> tty = ser->tty
>>
>> ser_release()
>> tty = ser->tty
>> dev_close(ser->dev)
>> unregister_netdevice(ser->dev)
>> debugfs_deinit(ser)
>> tty_kref_put(tty) // may drop the last ref
>> <-- race window -->
>> tty->ops->write(tty, ...) // UAF
>>
> What is unclear is -- why is the xmit callback still active after
> unregister_netdevice().

In my understanding, no new ndo_start_xmit should begin after
unregister_netdevice() has completed, but an in-flight TX still needs
proper synchronization with teardown.

Concretely, CPU1 enters the TX path (ndo_start_xmit -> caif_xmit ->
handle_tx) and reads ser->tty to use it. Before CPU1 actually uses the
tty, CPU0 drops the last tty kref during teardown, so the tty may get
freed. CPU1 then continues and dereferences the stale tty in
tty_write_room() / tty->ops->write(), triggering the UAF.

The KASAN stack trace is in the report:
https://groups.google.com/g/syzkaller/c/usNe0oKtoXw/m/x8qUc3yUAQAJ

Please let me know if I’m missing anything.

Best,
Shuangpeng