From patchwork Thu Dec 22 10:15:52 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Torvald Riegel X-Patchwork-Id: 88838 Delivered-To: patch@linaro.org Received: by 10.140.20.101 with SMTP id 92csp2725291qgi; Thu, 22 Dec 2016 02:16:17 -0800 (PST) X-Received: by 10.84.136.1 with SMTP id 1mr17993206plk.152.1482401777037; Thu, 22 Dec 2016 02:16:17 -0800 (PST) Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id l33si30329910pld.41.2016.12.22.02.16.16 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 22 Dec 2016 02:16:17 -0800 (PST) Received-SPF: pass (google.com: domain of libc-alpha-return-76234-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@sourceware.org; spf=pass (google.com: domain of libc-alpha-return-76234-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=libc-alpha-return-76234-patch=linaro.org@sourceware.org DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:message-id:subject:from:to:cc:date :content-type:mime-version; q=dns; s=default; b=fPm74bDTQ/9iJzwe wx3OOMzyJVofUcq7dA9KKaEwfYVV1NpgVJfYHLaEuQieQKqRZTb5OQo1/k1plk4l XndRbb0BRHPaaWhc0+hmk0yrGMctUIj86FPcmGzO6ZkI3Ey20S/zrsIOc+owI+eA 0khd2lYPT/87BojJD48LiIJWKDs= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:message-id:subject:from:to:cc:date :content-type:mime-version; s=default; bh=u46EgBAEvAuoNoIGHScks3 CDz6Q=; b=GKxpeKm9kbD15T5EPjphYjhLaCl/IKz03+X9BQjj8kramCl7TjkM4v TlhBXVH/Au7fOXzMnEG4FON1kc+owqlUF/FRQbk0NwI4tr4eVk4QyTJMYBHLWzsf ibPaAuXA0peMxLMyJgXkvZ3LY7a2yJt69A+nlQnzJnN+bsGzev+Jg= Received: (qmail 57642 invoked by alias); 22 Dec 2016 10:16:07 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 57633 invoked by uid 89); 22 Dec 2016 10:16:07 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-5.0 required=5.0 tests=BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=childs X-HELO: mx1.redhat.com Message-ID: <1482401752.14990.777.camel@redhat.com> Subject: [PATCH] [BZ #19402] Clear list of acquired robust mutexes in the child process after forking. From: Torvald Riegel To: GLIBC Devel Cc: "Carlos O'Donell" , Florian Weimer Date: Thu, 22 Dec 2016 11:15:52 +0100 Mime-Version: 1.0 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 If we can agree on one of the requirements I'm proposing there, this patch fixes the core problem of bug 19402. (The reproducer of this bug reveals another issue on x86, for which I'll send a patch next.) 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. commit f5a07a158cfe1f5d6583c25eeb57ebbbe2fbee83 Author: Torvald Riegel Date: Wed Dec 21 13:37:19 2016 +0100 Clear list of acquired robust mutexes in the child process after forking. 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. 2016-12-22 Torvald Riegel [BZ #19402] * sysdeps/nptl/fork.c (__libc_fork): Clear list of acquired robust mutexes. diff --git a/sysdeps/nptl/fork.c b/sysdeps/nptl/fork.c index 32cecce..fd3a82d 100644 --- a/sysdeps/nptl/fork.c +++ b/sysdeps/nptl/fork.c @@ -162,12 +162,20 @@ __libc_fork (void) #endif #ifdef __NR_set_robust_list - /* Initialize the robust mutex list which has been reset during - the fork. We do not check for errors since if it fails here - it failed at process start as well and noone could have used - robust mutexes. We also do not have to set - self->robust_head.futex_offset since we inherit the correct - value from the parent. */ + /* 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. */ +# 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));