[PATCH] [BZ #19402] Clear list of acquired robust mutexes in the child process after forking.
Florian Weimer
fweimer@redhat.com
Thu Dec 22 12:22:00 GMT 2016
On 12/22/2016 11:15 AM, Torvald Riegel wrote:
> I've asked for comments on whether mutexes acquired before fork() remain
> to be acquired by just the parent process after fork():
> https://sourceware.org/ml/libc-alpha/2016-12/msg00772.html
The conceptual problem here is that we need to effectively
process-shared mutexes differently from those which are process-private.
With effectively process-shared, I mean that the mutex object resides
on a mapping which is not copied by fork, but remains shared with the
parent.
I'm going to comment on the other thread as well.
> The fix is:
>
> Robust mutexes acquired at the time of a call to fork() do not remain
> acquired by the forked child process. We have to clear the list of
> acquired robust mutexes before registering this list with the kernel;
> otherwise, if some of the robust mutexes are process-shared, the parent
> process can alter the child's robust mutex list, which can lead to
> deadlocks or even modification of memory that may not be occupied by a
> mutex anymore.
>
> Tested on x86_64-linux with glibc's tests and the reproducer from 19402.
Can we add a test case for this?
> + /* Initialize the robust mutex list setting in the kernel which has
> + been reset during the fork. We do not check for errors because if
> + it fails here, it must have failed at process startup as well and
> + nobody could have used robust mutexes.
> + Before we do that, we have to clear the list of robust mutexes
> + because we do not inherit ownership of mutexes from the parent.
> + We do not have to set self->robust_head.futex_offset since we do
> + inherit the correct value from the parent. We do not need to clear
> + the pending operation because it must have been zero when fork was
> + called. */
fork is supposed to be async-signal-safe, so I'm not sure the comment
about the pending operation is completely correct.
(Our fork implementation is currently not async-signal-safe, though.)
> +# ifdef __PTHREAD_MUTEX_HAVE_PREV
> + self->robust_prev = &self->robust_head;
> +# endif
> + self->robust_head.list = &self->robust_head;
> # ifdef SHARED
> if (__builtin_expect (__libc_pthread_functions_init, 0))
> PTHFCT_CALL (ptr_set_robust, (self));
The change as such looks good to me, assuming this is the semantics we
want. I checked it matches the initialization code, and it comes before
the set_robust_list call, as required.
Thanks,
Florian
More information about the Libc-alpha
mailing list