Summary: | Race condition in pthread_kill | ||
---|---|---|---|
Product: | glibc | Reporter: | Rich Felker <bugdal> |
Component: | nptl | Assignee: | Florian Weimer <fweimer> |
Status: | RESOLVED FIXED | ||
Severity: | normal | CC: | fweimer, ppluzhnikov |
Priority: | P2 | Flags: | fweimer:
security-
|
Version: | unspecified | ||
Target Milestone: | 2.35 | ||
See Also: |
https://bugzilla.redhat.com/show_bug.cgi?id=1994068 https://sourceware.org/bugzilla/show_bug.cgi?id=28361 |
||
Host: | Target: | ||
Build: | Last reconfirmed: |
Description
Rich Felker
2011-06-15 00:39:17 UTC
POSIX says: “The lifetime of a thread ID ends after the thread terminates if it was created with the detachstate attribute set to PTHREAD_CREATE_DETACHED or if pthread_detach() or pthread_join() has been called for that thread.” How is this to be interpreted? This way? TERMINATED && (CREATED-AS-DETACHED || DETACH-CALLED || JOIN-CALLED) Or this way? (TERMINATED && CREATED-AS-DETACHED) || DETACH-CALLED || JOIN-CALLED In the second case, pthread_detach and pthread_join could just clear the TID in the thread descriptor to avoid the race, before reaping the TID from the kernel. If the second interpretation were the intented one, then the following paragraph would not have been necessary, since no function could be called on a detached thread. The first interpretation is correct but it does not matter because there is no such thing as "reaping the tid". The tid is available for reuse immediately when the SYS_exit syscall is made by pthread_exit or equivalent. *** Bug 19193 has been marked as a duplicate of this bug. *** The master branch has been updated by Florian Weimer <fw@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=8af8456004edbab71f8903a60a3cae442cf6fe69 commit 8af8456004edbab71f8903a60a3cae442cf6fe69 Author: Florian Weimer <fweimer@redhat.com> Date: Mon Sep 13 11:06:08 2021 +0200 nptl: pthread_kill, pthread_cancel should not fail after exit (bug 19193) This closes one remaining race condition related to bug 12889: if the thread already exited on the kernel side, returning ESRCH is not correct because that error is reserved for the thread IDs (pthread_t values) whose lifetime has ended. In case of a kernel-side exit and a valid thread ID, no signal needs to be sent and cancellation does not have an effect, so just return 0. sysdeps/pthread/tst-kill4.c triggers undefined behavior and is removed with this commit. Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> Fixed for 2.35 via: commit 526c3cf11ee9367344b6b15d669e4c3cb461a2be Author: Florian Weimer <fweimer@redhat.com> Date: Mon Sep 13 11:06:08 2021 +0200 nptl: Fix race between pthread_kill and thread exit (bug 12889) A new thread exit lock and flag are introduced. They are used to detect that the thread is about to exit or has exited in __pthread_kill_internal, and the signal is not sent in this case. The test sysdeps/pthread/tst-pthread_cancel-select-loop.c is derived from a downstream test originally written by Marek Polacek. Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> The release/2.34/master branch has been updated by Florian Weimer <fw@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=3abf3bd4edc86fb28c099cc85203cb46a811e0b8 commit 3abf3bd4edc86fb28c099cc85203cb46a811e0b8 Author: Florian Weimer <fweimer@redhat.com> Date: Mon Sep 13 11:06:08 2021 +0200 nptl: pthread_kill, pthread_cancel should not fail after exit (bug 19193) This closes one remaining race condition related to bug 12889: if the thread already exited on the kernel side, returning ESRCH is not correct because that error is reserved for the thread IDs (pthread_t values) whose lifetime has ended. In case of a kernel-side exit and a valid thread ID, no signal needs to be sent and cancellation does not have an effect, so just return 0. sysdeps/pthread/tst-kill4.c triggers undefined behavior and is removed with this commit. Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> (cherry picked from commit 8af8456004edbab71f8903a60a3cae442cf6fe69) The master branch has been updated by Florian Weimer <fw@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=2849e2f53311b66853cb5159b64cba2bddbfb854 commit 2849e2f53311b66853cb5159b64cba2bddbfb854 Author: Florian Weimer <fweimer@redhat.com> Date: Thu Sep 23 09:55:54 2021 +0200 nptl: Avoid setxid deadlock with blocked signals in thread exit [BZ #28361] As part of the fix for bug 12889, signals are blocked during thread exit, so that application code cannot run on the thread that is about to exit. This would cause problems if the application expected signals to be delivered after the signal handler revealed the thread to still exist, despite pthread_kill can no longer be used to send signals to it. However, glibc internally uses the SIGSETXID signal in a way that is incompatible with signal blocking, due to the way the setxid handshake delays thread exit until the setxid operation has completed. With a blocked SIGSETXID, the handshake can never complete, causing a deadlock. As a band-aid, restore the previous handshake protocol by not blocking SIGSETXID during thread exit. The new test sysdeps/pthread/tst-pthread-setuid-loop.c is based on a downstream test by Martin Osvald. Reviewed-by: Carlos O'Donell <carlos@redhat.com> Tested-by: Carlos O'Donell <carlos@redhat.com> The release/2.34/master branch has been updated by Florian Weimer <fw@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=33adeaa3e2b9143c38884bc5aa65ded222ed274e commit 33adeaa3e2b9143c38884bc5aa65ded222ed274e Author: Florian Weimer <fweimer@redhat.com> Date: Thu Sep 23 09:55:54 2021 +0200 nptl: Avoid setxid deadlock with blocked signals in thread exit [BZ #28361] As part of the fix for bug 12889, signals are blocked during thread exit, so that application code cannot run on the thread that is about to exit. This would cause problems if the application expected signals to be delivered after the signal handler revealed the thread to still exist, despite pthread_kill can no longer be used to send signals to it. However, glibc internally uses the SIGSETXID signal in a way that is incompatible with signal blocking, due to the way the setxid handshake delays thread exit until the setxid operation has completed. With a blocked SIGSETXID, the handshake can never complete, causing a deadlock. As a band-aid, restore the previous handshake protocol by not blocking SIGSETXID during thread exit. The new test sysdeps/pthread/tst-pthread-setuid-loop.c is based on a downstream test by Martin Osvald. Reviewed-by: Carlos O'Donell <carlos@redhat.com> Tested-by: Carlos O'Donell <carlos@redhat.com> (cherry picked from commit 2849e2f53311b66853cb5159b64cba2bddbfb854) |