Re: [PATCH] tty: ldisc: fix deadlock between ldisc_sem and rtnl_mutex
From: Zhou, Yun
Date: Mon Jul 20 2026 - 08:55:49 EST
On 7/17/26 18:53, Greg KH wrote:
CAUTION: This email comes from a non Wind River email account!
Do not click links or open attachments unless you recognize the sender and know the content is safe.
On Thu, Jul 16, 2026 at 02:47:19PM +0800, Yun Zhou wrote:
syzbot reported a circular lock dependency involving tty ldisc_sem and
the networking rtnl_mutex. The full chain is:
rtnl_mutex --> nft_commit_mutex --> ... --> ep->mtx --> ldisc_sem --> rtnl_mutex
The last edge (ldisc_sem -> rtnl_mutex) is created because tty line
discipline .open() callbacks (slcan, slip) call register_netdev() which
acquires rtnl_mutex, and .open() runs under ldisc_sem write lock in
tty_set_ldisc().
Fix by moving the .open() call outside the ldisc_sem write lock. The
ldisc .open() is initialization of the NEW discipline after the old one
has been closed - there is no need for ldisc_sem protection at this
point since:
- tty_lock is held throughout, preventing concurrent tty_set_ldisc,
hangup, or close
- tty->ldisc is set to NULL during the window, so concurrent readers
(tty_ldisc_ref, tty_ldisc_ref_wait) see NULL and return immediately,
which callers already handle as a hangup condition
- tty buffer data stays queued until the ldisc is installed
Ah, but look at the review at:
https://sashiko.dev/#/patchset/20260716064719.1401892-1-yun.zhou@xxxxxxxxxxxxx
which says:
Does unlocking the semaphore while the ldisc pointer is NULL introduce a UAPI
break for concurrent operations?
If a concurrent process calls read(), write(), or poll() during this unlocked
window, it can enter tty_ldisc_ref_wait() in drivers/tty/tty_io.c. Because the
semaphore was unlocked here, tty_ldisc_ref_wait() will successfully acquire
the read lock but observe tty->ldisc as NULL.
This causes the reader to immediately return EOF or -EIO, potentially
aborting userspace applications unexpectedly during a line discipline
transition.
Is that not true?
No, the issue reported by Sashiko does indeed exist. I will fix it in the v2.