public inbox for glibc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug nptl/19951] Use after free in pthread_detach
       [not found] <bug-19951-131@http.sourceware.org/bugzilla/>
@ 2021-06-03 14:06 ` adhemerval.zanella at linaro dot org
  0 siblings, 0 replies; only message in thread
From: adhemerval.zanella at linaro dot org @ 2021-06-03 14:06 UTC (permalink / raw)
  To: glibc-bugs

https://sourceware.org/bugzilla/show_bug.cgi?id=19951

Adhemerval Zanella <adhemerval.zanella at linaro dot org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |adhemerval.zanella at linaro dot o
                   |                            |rg

--- Comment #2 from Adhemerval Zanella <adhemerval.zanella at linaro dot org> ---
I think the problem is relying the the set_tid_address value to synchronize the
thread state (joined, detached, terminated). 

First there are disjoined fields, so on every state operations (pthread_detach,
pthread_join, and pthread_exit/thread exit) we need to check for both fields
and handle possible partial results (as for pthread_join which first sets the
PD joinid field, wait for kernel, and resets the joinid in case of failure).

Second we don't really need the kernel exit execution advertisement, since the
synchronization required is to setup which thread would be responsible to
cleanup the allocated resources.

So I think we need to use a different field with 4 states to synchronize
between pthread_create, pthread_join, pthread_detached, and pthread_exit:

1. On thread creation the inital state is JOINABLE or DETACHED (depending of
the pthread_attribute).

2. On pthread_detach call, a CAS is done on the state field.  If the CAS fails
it means that thread is already detached (EINVAL) or the threads is exitng or
EXITED and it pthread_detach should be reponsible to join the thread and
deallocate the resource.

3. On pthread_create exit phase (reached either thread function has returned,
pthread_exit has being called, or cancellation handled has been acted upon) we
also issue a CAS over state field to initial the EXITTING mode.  If the thread
is already on DETACHED mode it will be thread itself responsible to deallocate
any resource.  In the final pthread exit phase the state is set to EXITED and a
futex wake is done (to synchronize with pthread_join). The EXITING mode exists
to avoid a pthread_detach to wrongly setup the mode while the thread calling
the required exit functions, but has not while deallocate the stack.

4. Finally the pthread_join implementation is much more simpler: the futex wait
is done directly on thread state and there is no need to reset it in case of
TIMEOUT (since the state is now set either by pthread_detached or
pthread_create exit phase).

This issue should be fixed because once pthread_join synchronizes the thread
state it can exit early in the case of DETACHED since the thread itself will be
responsible to cleanup its own memory. Arguably it is undefined behaviour to
try join a detached thread, but glibc tries to catch such issues where
possible, it would not be possible to catch the isseu trying to join a detached
thread that has already exited.

I am working a possible fix.

-- 
You are receiving this mail because:
You are on the CC list for the bug.

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-06-03 14:06 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <bug-19951-131@http.sourceware.org/bugzilla/>
2021-06-03 14:06 ` [Bug nptl/19951] Use after free in pthread_detach adhemerval.zanella at linaro dot org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).