Re: [PATCH v3] tty: ldisc: fix deadlock between ldisc_sem and rtnl_mutex

"Zhou, Yun" <[email protected]>
Newsgroups dev.linux.lists.sashiko-reviews,org.kernel.vger.linux-can
Message-ID <[email protected]>
On 7/25/2026 4:47 PM, [email protected] wrote:
> Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
> 
> New issues:
> - [High] The patch replaces a lockdep splat with a silent waitqueue deadlock on the success path.
> 
> Pre-existing issues:
> - [High] Incomplete fix for circular locking between ldisc_sem and rtnl_mutex, leaving deadlocks on teardown, error, and hangup paths.
> --
> 
> --- Patch [1]: [PATCH v3] tty: ldisc: fix deadlock between ldisc_sem and rtnl_mutex ---
> commit 98cde28b47f83f4a2bf71bb1e35f53d9a7a36294
> Author: Yun Zhou <[email protected]>
> 
> tty: ldisc: fix deadlock between ldisc_sem and rtnl_mutex
> 
> This commit attempts to fix a circular lock dependency between ldisc_sem
> and rtnl_mutex reported by syzbot. It moves the tty line discipline .open()
> callback outside the ldisc_sem write lock in tty_set_ldisc(). It also adds
> logic in tty_ldisc_ref_wait() to wait for the ldisc transition to complete.
> 
> Closes: https://syzkaller.appspot.com/bug?extid=de610eeef174bd59a8a3
> 
>> diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
>> index 27fe8236f6623..6ec93e6b84988 100644
>> --- a/drivers/tty/tty_ldisc.c
>> +++ b/drivers/tty/tty_ldisc.c
>> @@ -242,6 +242,16 @@ struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty)
>>
>>        ldsem_down_read(&tty->ldisc_sem, MAX_SCHEDULE_TIMEOUT);
>>        ld = tty->ldisc;
>> +     while (!ld && !test_bit(TTY_HUPPED, &tty->flags)) {
>> +             ldsem_up_read(&tty->ldisc_sem);
>> +
>> +             /* ldisc may be NULL during a discipline switch; wait and retry */
>> +             wait_event(tty->read_wait,
>> +                        READ_ONCE(tty->ldisc) != NULL ||
>> +                        test_bit(TTY_HUPPED, &tty->flags));
> 
> [Severity: High]
> Does this wait_event() create a silent waitqueue deadlock that replaces the
> lockdep splat?
> 
> If thread A switches to a network ldisc like slcan, it will set tty->ldisc
> to NULL in tty_set_ldisc() and drop ldisc_sem, but then block waiting for
> rtnl_mutex in the .open() callback.
> 
> Concurrently, if thread B already holds rtnl_mutex and calls tty_poll(),
> it enters tty_ldisc_ref_wait() here. Thread B will observe tty->ldisc as NULL
> and block uninterruptibly in this wait_event(), waiting for thread A to
> re-assign tty->ldisc.
> 

No, this scenario does not exist. tty_poll() is only called from 
userspace poll/epoll/select paths, which never hold rtnl_mutex. And All 
callers of tty_ldisc_ref_wait() are userspace entry points: 
tty_read/tty_write/tty_poll/tty_ioctl/tty_open/tty_show_fdinfo/paste_selection/tty_perform_flush. 
None of these are reachable from any code path that holds rtnl_mutex.

> Since thread A is blocked waiting for thread B to release rtnl_mutex,
> will both threads hang forever without a lockdep warning?
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.