From patchwork Fri Mar 2 16:18:55 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herton Ronaldo Krzesinski X-Patchwork-Id: 144278 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from chlorine.canonical.com (chlorine.canonical.com [91.189.94.204]) by ozlabs.org (Postfix) with ESMTP id C7A63B6F62 for ; Sat, 3 Mar 2012 03:19:14 +1100 (EST) Received: from localhost ([127.0.0.1] helo=chlorine.canonical.com) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1S3VCE-00084J-Da; Fri, 02 Mar 2012 16:19:06 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1S3VCB-000846-0P for kernel-team@lists.ubuntu.com; Fri, 02 Mar 2012 16:19:03 +0000 Received: from 201.47.15.206.dynamic.adsl.gvt.net.br ([201.47.15.206] helo=canonical.com) by youngberry.canonical.com with esmtpsa (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1S3VCA-0000ya-B0 for kernel-team@lists.ubuntu.com; Fri, 02 Mar 2012 16:19:02 +0000 From: "Herton R. Krzesinski" To: kernel-team@lists.ubuntu.com Subject: [Natty/SRU][PATCH] ipc/sem.c: fix race with concurrent semtimedop() timeouts and IPC_RMID Date: Fri, 2 Mar 2012 13:18:55 -0300 Message-Id: <1330705135-15096-2-git-send-email-herton.krzesinski@canonical.com> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1330705135-15096-1-git-send-email-herton.krzesinski@canonical.com> References: <1330705135-15096-1-git-send-email-herton.krzesinski@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.13 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: kernel-team-bounces@lists.ubuntu.com Errors-To: kernel-team-bounces@lists.ubuntu.com From: Manfred Spraul If a semaphore array is removed and in parallel a sleeping task is woken up (signal or timeout, does not matter), then the woken up task does not wait until wake_up_sem_queue_do() is completed. This will cause crashes, because wake_up_sem_queue_do() will read from a stale pointer. The fix is simple: Regardless of anything, always call get_queue_result(). This function waits until wake_up_sem_queue_do() has finished it's task. Addresses https://bugzilla.kernel.org/show_bug.cgi?id=27142 Reported-by: Yuriy Yevtukhov Reported-by: Harald Laabs Signed-off-by: Manfred Spraul Acked-by: Eric Dumazet Cc: [2.6.35+] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds (cherry-picked from commit d694ad62bf539dbb20a0899ac2a954555f9e4a83 upstream) BugLink: http://bugs.launchpad.net/bugs/943815 Signed-off-by: Herton Ronaldo Krzesinski --- ipc/sem.c | 13 +++++++++++-- 1 files changed, 11 insertions(+), 2 deletions(-) diff --git a/ipc/sem.c b/ipc/sem.c index 0e0d49b..9769b47 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -1454,15 +1454,24 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops, } sma = sem_lock(ns, semid); + + /* + * Wait until it's guaranteed that no wakeup_sem_queue_do() is ongoing. + */ + error = get_queue_result(&queue); + + /* + * Array removed? If yes, leave without sem_unlock(). + */ if (IS_ERR(sma)) { error = -EIDRM; goto out_free; } - error = get_queue_result(&queue); /* - * If queue.status != -EINTR we are woken up by another process + * If queue.status != -EINTR we are woken up by another process. + * Leave without unlink_queue(), but with sem_unlock(). */ if (error != -EINTR) {