lkml.org 
[lkml]   [2011]   [Jul]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH] [5/50] ipc/sem.c: fix race with concurrent semtimedop() timeouts
    Date
    2.6.35-longterm review patch.  If anyone has any objections, please let me know.

    ------------------
    From: Manfred Spraul <manfred@colorfullife.com>

    [ upstream commit d694ad62bf539dbb20a0899ac2a954555f9e4a83 ]
    and IPC_RMID

    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 <yuriy@ucoz.com>
    Reported-by: Harald Laabs <kernel@dasr.de>
    Signed-off-by: Manfred Spraul <manfred@colorfullife.com>
    Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
    Cc: <stable@kernel.org> [2.6.35+]
    Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
    Signed-off-by: Andi Kleen <ak@linux.intel.com>

    Index: linux-2.6.35.y/ipc/sem.c
    ===================================================================
    --- linux-2.6.35.y.orig/ipc/sem.c
    +++ linux-2.6.35.y/ipc/sem.c
    @@ -1452,15 +1452,24 @@ SYSCALL_DEFINE4(semtimedop, int, semid,
    }

    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) {

    \
     
     \ /
      Last update: 2011-07-29 01:53    [W:0.023 / U:153.684 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site