source: trunk/server/common/patches/cve-2014-3153-3.patch @ 2557

Last change on this file since 2557 was 2557, checked in by achernya, 10 years ago
Kernel patches against cve-2014-3153 (old, uncommitted changes)
File size: 3.2 KB
  • kernel/futex.c

    From 9ad5dabd87e8dd5506529e12e4e8c7b25fb88d7a Mon Sep 17 00:00:00 2001
    From: Thomas Gleixner <tglx@linutronix.de>
    Date: Tue, 3 Jun 2014 12:27:07 +0000
    Subject: [PATCH 3/4] futex: Always cleanup owner tid in unlock_pi
    
    commit 13fbca4c6ecd96ec1a1cfa2e4f2ce191fe928a5e upstream.
    
    If the owner died bit is set at futex_unlock_pi, we currently do not
    cleanup the user space futex.  So the owner TID of the current owner
    (the unlocker) persists.  That's observable inconsistant state,
    especially when the ownership of the pi state got transferred.
    
    Clean it up unconditionally.
    
    Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
    Cc: Kees Cook <keescook@chromium.org>
    Cc: Will Drewry <wad@chromium.org>
    Cc: Darren Hart <dvhart@linux.intel.com>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
     kernel/futex.c |   40 ++++++++++++++++++----------------------
     1 file changed, 18 insertions(+), 22 deletions(-)
    
    diff --git a/kernel/futex.c b/kernel/futex.c
    index 8c1e6d0..9720c42 100644
    a b static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this) 
    903903        struct task_struct *new_owner;
    904904        struct futex_pi_state *pi_state = this->pi_state;
    905905        u32 uninitialized_var(curval), newval;
     906        int ret = 0;
    906907
    907908        if (!pi_state)
    908909                return -EINVAL;
    static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this) 
    926927                new_owner = this->task;
    927928
    928929        /*
    929          * We pass it to the next owner. (The WAITERS bit is always
    930          * kept enabled while there is PI state around. We must also
    931          * preserve the owner died bit.)
     930         * We pass it to the next owner. The WAITERS bit is always
     931         * kept enabled while there is PI state around. We cleanup the
     932         * owner died bit, because we are the owner.
    932933         */
    933         if (!(uval & FUTEX_OWNER_DIED)) {
    934                 int ret = 0;
    935 
    936                 newval = FUTEX_WAITERS | task_pid_vnr(new_owner);
     934        newval = FUTEX_WAITERS | task_pid_vnr(new_owner);
    937935
    938                 if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval))
    939                         ret = -EFAULT;
    940                 else if (curval != uval)
    941                         ret = -EINVAL;
    942                 if (ret) {
    943                         raw_spin_unlock(&pi_state->pi_mutex.wait_lock);
    944                         return ret;
    945                 }
     936        if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval))
     937                ret = -EFAULT;
     938        else if (curval != uval)
     939                ret = -EINVAL;
     940        if (ret) {
     941                raw_spin_unlock(&pi_state->pi_mutex.wait_lock);
     942                return ret;
    946943        }
    947944
    948945        raw_spin_lock_irq(&pi_state->owner->pi_lock);
    retry: 
    21872184        /*
    21882185         * To avoid races, try to do the TID -> 0 atomic transition
    21892186         * again. If it succeeds then we can return without waking
    2190          * anyone else up:
     2187         * anyone else up. We only try this if neither the waiters nor
     2188         * the owner died bit are set.
    21912189         */
    2192         if (!(uval & FUTEX_OWNER_DIED) &&
     2190        if (!(uval & ~FUTEX_TID_MASK) &&
    21932191            cmpxchg_futex_value_locked(&uval, uaddr, vpid, 0))
    21942192                goto pi_faulted;
    21952193        /*
    retry: 
    22212219        /*
    22222220         * No waiters - kernel unlocks the futex:
    22232221         */
    2224         if (!(uval & FUTEX_OWNER_DIED)) {
    2225                 ret = unlock_futex_pi(uaddr, uval);
    2226                 if (ret == -EFAULT)
    2227                         goto pi_faulted;
    2228         }
     2222        ret = unlock_futex_pi(uaddr, uval);
     2223        if (ret == -EFAULT)
     2224                goto pi_faulted;
    22292225
    22302226out_unlock:
    22312227        spin_unlock(&hb->lock);
Note: See TracBrowser for help on using the repository browser.