<feed xmlns='http://www.w3.org/2005/Atom'>
<title>linux-stable.git/drivers/tty/tty_jobctrl.c, branch v4.14.331</title>
<subtitle>Linux kernel stable tree</subtitle>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux-stable.git/'/>
<entry>
<title>tty: tty_jobctrl: fix pid memleak in disassociate_ctty()</title>
<updated>2023-11-20T09:27:34+00:00</updated>
<author>
<name>Yi Yang</name>
<email>yiyang13@huawei.com</email>
</author>
<published>2023-08-31T02:33:29+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux-stable.git/commit/?id=2510575d81d8f528e00b1fe7b540e2be0959bd2b'/>
<id>2510575d81d8f528e00b1fe7b540e2be0959bd2b</id>
<content type='text'>
[ Upstream commit 11e7f27b79757b6586645d87b95d5b78375ecdfc ]

There is a pid leakage:
------------------------------
unreferenced object 0xffff88810c181940 (size 224):
  comm "sshd", pid 8191, jiffies 4294946950 (age 524.570s)
  hex dump (first 32 bytes):
    01 00 00 00 00 00 00 00 00 00 00 00 ad 4e ad de  .............N..
    ff ff ff ff 6b 6b 6b 6b ff ff ff ff ff ff ff ff  ....kkkk........
  backtrace:
    [&lt;ffffffff814774e6&gt;] kmem_cache_alloc+0x5c6/0x9b0
    [&lt;ffffffff81177342&gt;] alloc_pid+0x72/0x570
    [&lt;ffffffff81140ac4&gt;] copy_process+0x1374/0x2470
    [&lt;ffffffff81141d77&gt;] kernel_clone+0xb7/0x900
    [&lt;ffffffff81142645&gt;] __se_sys_clone+0x85/0xb0
    [&lt;ffffffff8114269b&gt;] __x64_sys_clone+0x2b/0x30
    [&lt;ffffffff83965a72&gt;] do_syscall_64+0x32/0x80
    [&lt;ffffffff83a00085&gt;] entry_SYSCALL_64_after_hwframe+0x61/0xc6

It turns out that there is a race condition between disassociate_ctty() and
tty_signal_session_leader(), which caused this leakage.

The pid memleak is triggered by the following race:
task[sshd]                     task[bash]
-----------------------        -----------------------
                               disassociate_ctty();
                               spin_lock_irq(&amp;current-&gt;sighand-&gt;siglock);
                               put_pid(current-&gt;signal-&gt;tty_old_pgrp);
                               current-&gt;signal-&gt;tty_old_pgrp = NULL;
                               tty = tty_kref_get(current-&gt;signal-&gt;tty);
                               spin_unlock_irq(&amp;current-&gt;sighand-&gt;siglock);
tty_vhangup();
tty_lock(tty);
...
tty_signal_session_leader();
spin_lock_irq(&amp;p-&gt;sighand-&gt;siglock);
...
if (tty-&gt;ctrl.pgrp) //tty-&gt;ctrl.pgrp is not NULL
p-&gt;signal-&gt;tty_old_pgrp = get_pid(tty-&gt;ctrl.pgrp); //An extra get
spin_unlock_irq(&amp;p-&gt;sighand-&gt;siglock);
...
tty_unlock(tty);
                               if (tty) {
                                   tty_lock(tty);
                                   ...
                                   put_pid(tty-&gt;ctrl.pgrp);
                                   tty-&gt;ctrl.pgrp = NULL; //It's too late
                                   ...
                                   tty_unlock(tty);
                               }

The issue is believed to be introduced by commit c8bcd9c5be24 ("tty:
Fix -&gt;session locking") who moves the unlock of siglock in
disassociate_ctty() above "if (tty)", making a small window allowing
tty_signal_session_leader() to kick in. It can be easily reproduced by
adding a delay before "if (tty)" and at the entrance of
tty_signal_session_leader().

To fix this issue, we move "put_pid(current-&gt;signal-&gt;tty_old_pgrp)" after
"tty-&gt;ctrl.pgrp = NULL".

Fixes: c8bcd9c5be24 ("tty: Fix -&gt;session locking")
Signed-off-by: Yi Yang &lt;yiyang13@huawei.com&gt;
Co-developed-by: GUO Zihua &lt;guozihua@huawei.com&gt;
Signed-off-by: GUO Zihua &lt;guozihua@huawei.com&gt;
Link: https://lore.kernel.org/r/20230831023329.165737-1-yiyang13@huawei.com
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
Signed-off-by: Sasha Levin &lt;sashal@kernel.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
[ Upstream commit 11e7f27b79757b6586645d87b95d5b78375ecdfc ]

There is a pid leakage:
------------------------------
unreferenced object 0xffff88810c181940 (size 224):
  comm "sshd", pid 8191, jiffies 4294946950 (age 524.570s)
  hex dump (first 32 bytes):
    01 00 00 00 00 00 00 00 00 00 00 00 ad 4e ad de  .............N..
    ff ff ff ff 6b 6b 6b 6b ff ff ff ff ff ff ff ff  ....kkkk........
  backtrace:
    [&lt;ffffffff814774e6&gt;] kmem_cache_alloc+0x5c6/0x9b0
    [&lt;ffffffff81177342&gt;] alloc_pid+0x72/0x570
    [&lt;ffffffff81140ac4&gt;] copy_process+0x1374/0x2470
    [&lt;ffffffff81141d77&gt;] kernel_clone+0xb7/0x900
    [&lt;ffffffff81142645&gt;] __se_sys_clone+0x85/0xb0
    [&lt;ffffffff8114269b&gt;] __x64_sys_clone+0x2b/0x30
    [&lt;ffffffff83965a72&gt;] do_syscall_64+0x32/0x80
    [&lt;ffffffff83a00085&gt;] entry_SYSCALL_64_after_hwframe+0x61/0xc6

It turns out that there is a race condition between disassociate_ctty() and
tty_signal_session_leader(), which caused this leakage.

The pid memleak is triggered by the following race:
task[sshd]                     task[bash]
-----------------------        -----------------------
                               disassociate_ctty();
                               spin_lock_irq(&amp;current-&gt;sighand-&gt;siglock);
                               put_pid(current-&gt;signal-&gt;tty_old_pgrp);
                               current-&gt;signal-&gt;tty_old_pgrp = NULL;
                               tty = tty_kref_get(current-&gt;signal-&gt;tty);
                               spin_unlock_irq(&amp;current-&gt;sighand-&gt;siglock);
tty_vhangup();
tty_lock(tty);
...
tty_signal_session_leader();
spin_lock_irq(&amp;p-&gt;sighand-&gt;siglock);
...
if (tty-&gt;ctrl.pgrp) //tty-&gt;ctrl.pgrp is not NULL
p-&gt;signal-&gt;tty_old_pgrp = get_pid(tty-&gt;ctrl.pgrp); //An extra get
spin_unlock_irq(&amp;p-&gt;sighand-&gt;siglock);
...
tty_unlock(tty);
                               if (tty) {
                                   tty_lock(tty);
                                   ...
                                   put_pid(tty-&gt;ctrl.pgrp);
                                   tty-&gt;ctrl.pgrp = NULL; //It's too late
                                   ...
                                   tty_unlock(tty);
                               }

The issue is believed to be introduced by commit c8bcd9c5be24 ("tty:
Fix -&gt;session locking") who moves the unlock of siglock in
disassociate_ctty() above "if (tty)", making a small window allowing
tty_signal_session_leader() to kick in. It can be easily reproduced by
adding a delay before "if (tty)" and at the entrance of
tty_signal_session_leader().

To fix this issue, we move "put_pid(current-&gt;signal-&gt;tty_old_pgrp)" after
"tty-&gt;ctrl.pgrp = NULL".

Fixes: c8bcd9c5be24 ("tty: Fix -&gt;session locking")
Signed-off-by: Yi Yang &lt;yiyang13@huawei.com&gt;
Co-developed-by: GUO Zihua &lt;guozihua@huawei.com&gt;
Signed-off-by: GUO Zihua &lt;guozihua@huawei.com&gt;
Link: https://lore.kernel.org/r/20230831023329.165737-1-yiyang13@huawei.com
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
Signed-off-by: Sasha Levin &lt;sashal@kernel.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>tty: Fix -&gt;session locking</title>
<updated>2020-12-11T12:39:04+00:00</updated>
<author>
<name>Jann Horn</name>
<email>jannh@google.com</email>
</author>
<published>2020-12-03T01:25:05+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux-stable.git/commit/?id=8deb3d9018400fab0a7401a910d3341053f5ec82'/>
<id>8deb3d9018400fab0a7401a910d3341053f5ec82</id>
<content type='text'>
commit c8bcd9c5be24fb9e6132e97da5a35e55a83e36b9 upstream.

Currently, locking of -&gt;session is very inconsistent; most places
protect it using the legacy tty mutex, but disassociate_ctty(),
__do_SAK(), tiocspgrp() and tiocgsid() don't.
Two of the writers hold the ctrl_lock (because they already need it for
-&gt;pgrp), but __proc_set_tty() doesn't do that yet.

On a PREEMPT=y system, an unprivileged user can theoretically abuse
this broken locking to read 4 bytes of freed memory via TIOCGSID if
tiocgsid() is preempted long enough at the right point. (Other things
might also go wrong, especially if root-only ioctls are involved; I'm
not sure about that.)

Change the locking on -&gt;session such that:

 - tty_lock() is held by all writers: By making disassociate_ctty()
   hold it. This should be fine because the same lock can already be
   taken through the call to tty_vhangup_session().
   The tricky part is that we need to shorten the area covered by
   siglock to be able to take tty_lock() without ugly retry logic; as
   far as I can tell, this should be fine, since nothing in the
   signal_struct is touched in the `if (tty)` branch.
 - ctrl_lock is held by all writers: By changing __proc_set_tty() to
   hold the lock a little longer.
 - All readers that aren't holding tty_lock() hold ctrl_lock: By
   adding locking to tiocgsid() and __do_SAK(), and expanding the area
   covered by ctrl_lock in tiocspgrp().

Cc: stable@kernel.org
Signed-off-by: Jann Horn &lt;jannh@google.com&gt;
Reviewed-by: Jiri Slaby &lt;jirislaby@kernel.org&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;

</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
commit c8bcd9c5be24fb9e6132e97da5a35e55a83e36b9 upstream.

Currently, locking of -&gt;session is very inconsistent; most places
protect it using the legacy tty mutex, but disassociate_ctty(),
__do_SAK(), tiocspgrp() and tiocgsid() don't.
Two of the writers hold the ctrl_lock (because they already need it for
-&gt;pgrp), but __proc_set_tty() doesn't do that yet.

On a PREEMPT=y system, an unprivileged user can theoretically abuse
this broken locking to read 4 bytes of freed memory via TIOCGSID if
tiocgsid() is preempted long enough at the right point. (Other things
might also go wrong, especially if root-only ioctls are involved; I'm
not sure about that.)

Change the locking on -&gt;session such that:

 - tty_lock() is held by all writers: By making disassociate_ctty()
   hold it. This should be fine because the same lock can already be
   taken through the call to tty_vhangup_session().
   The tricky part is that we need to shorten the area covered by
   siglock to be able to take tty_lock() without ugly retry logic; as
   far as I can tell, this should be fine, since nothing in the
   signal_struct is touched in the `if (tty)` branch.
 - ctrl_lock is held by all writers: By changing __proc_set_tty() to
   hold the lock a little longer.
 - All readers that aren't holding tty_lock() hold ctrl_lock: By
   adding locking to tiocgsid() and __do_SAK(), and expanding the area
   covered by ctrl_lock in tiocspgrp().

Cc: stable@kernel.org
Signed-off-by: Jann Horn &lt;jannh@google.com&gt;
Reviewed-by: Jiri Slaby &lt;jirislaby@kernel.org&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;

</pre>
</div>
</content>
</entry>
<entry>
<title>tty: Fix -&gt;pgrp locking in tiocspgrp()</title>
<updated>2020-12-11T12:39:04+00:00</updated>
<author>
<name>Jann Horn</name>
<email>jannh@google.com</email>
</author>
<published>2020-12-03T01:25:04+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux-stable.git/commit/?id=882e038d2cd276163a8fc7bbeffda59ae0924471'/>
<id>882e038d2cd276163a8fc7bbeffda59ae0924471</id>
<content type='text'>
commit 54ffccbf053b5b6ca4f6e45094b942fab92a25fc upstream.

tiocspgrp() takes two tty_struct pointers: One to the tty that userspace
passed to ioctl() (`tty`) and one to the TTY being changed (`real_tty`).
These pointers are different when ioctl() is called with a master fd.

To properly lock real_tty-&gt;pgrp, we must take real_tty-&gt;ctrl_lock.

This bug makes it possible for racing ioctl(TIOCSPGRP, ...) calls on
both sides of a PTY pair to corrupt the refcount of `struct pid`,
leading to use-after-free errors.

Fixes: 47f86834bbd4 ("redo locking of tty-&gt;pgrp")
CC: stable@kernel.org
Signed-off-by: Jann Horn &lt;jannh@google.com&gt;
Reviewed-by: Jiri Slaby &lt;jirislaby@kernel.org&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
commit 54ffccbf053b5b6ca4f6e45094b942fab92a25fc upstream.

tiocspgrp() takes two tty_struct pointers: One to the tty that userspace
passed to ioctl() (`tty`) and one to the TTY being changed (`real_tty`).
These pointers are different when ioctl() is called with a master fd.

To properly lock real_tty-&gt;pgrp, we must take real_tty-&gt;ctrl_lock.

This bug makes it possible for racing ioctl(TIOCSPGRP, ...) calls on
both sides of a PTY pair to corrupt the refcount of `struct pid`,
leading to use-after-free errors.

Fixes: 47f86834bbd4 ("redo locking of tty-&gt;pgrp")
CC: stable@kernel.org
Signed-off-by: Jann Horn &lt;jannh@google.com&gt;
Reviewed-by: Jiri Slaby &lt;jirislaby@kernel.org&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>tty: split job control support into a file of its own</title>
<updated>2017-04-18T16:01:52+00:00</updated>
<author>
<name>Nicolas Pitre</name>
<email>nicolas.pitre@linaro.org</email>
</author>
<published>2017-04-12T22:37:16+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux-stable.git/commit/?id=a1235b3eb10086b8420f37bbb6c29436f55940ba'/>
<id>a1235b3eb10086b8420f37bbb6c29436f55940ba</id>
<content type='text'>
This makes it easier for job control to become optional and/or usable
independently from tty_io.c, as well as providing a nice purpose
separation. No logical changes from this patch.

Signed-off-by: Nicolas Pitre &lt;nico@linaro.org&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
This makes it easier for job control to become optional and/or usable
independently from tty_io.c, as well as providing a nice purpose
separation. No logical changes from this patch.

Signed-off-by: Nicolas Pitre &lt;nico@linaro.org&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</pre>
</div>
</content>
</entry>
</feed>
