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

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

    From cabef9fee397081ec3dfbde2955d4db675a96a4a Mon Sep 17 00:00:00 2001
    From: Thomas Gleixner <tglx@linutronix.de>
    Date: Mon, 12 May 2014 20:45:34 +0000
    Subject: [PATCH 1/1] futex: Add another early deadlock detection check
    
    commit 866293ee54227584ffcb4a42f69c1f365974ba7f upstream.
    
    Dave Jones trinity syscall fuzzer exposed an issue in the deadlock
    detection code of rtmutex:
      http://lkml.kernel.org/r/20140429151655.GA14277@redhat.com
    
    That underlying issue has been fixed with a patch to the rtmutex code,
    but the futex code must not call into rtmutex in that case because
        - it can detect that issue early
        - it avoids a different and more complex fixup for backing out
    
    If the user space variable got manipulated to 0x80000000 which means
    no lock holder, but the waiters bit set and an active pi_state in the
    kernel is found we can figure out the recursive locking issue by
    looking at the pi_state owner. If that is the current task, then we
    can safely return -EDEADLK.
    
    The check should have been added in commit 59fa62451 (futex: Handle
    futex_pi OWNER_DIED take over correctly) already, but I did not see
    the above issue caused by user space manipulation back then.
    
    Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
    Cc: Dave Jones <davej@redhat.com>
    Cc: Linus Torvalds <torvalds@linux-foundation.org>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Darren Hart <darren@dvhart.com>
    Cc: Davidlohr Bueso <davidlohr@hp.com>
    Cc: Steven Rostedt <rostedt@goodmis.org>
    Cc: Clark Williams <williams@redhat.com>
    Cc: Paul McKenney <paulmck@linux.vnet.ibm.com>
    Cc: Lai Jiangshan <laijs@cn.fujitsu.com>
    Cc: Roland McGrath <roland@hack.frob.com>
    Cc: Carlos ODonell <carlos@redhat.com>
    Cc: Jakub Jelinek <jakub@redhat.com>
    Cc: Michael Kerrisk <mtk.manpages@gmail.com>
    Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
    Link: http://lkml.kernel.org/r/20140512201701.097349971@linutronix.de
    Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
     kernel/futex.c |   47 ++++++++++++++++++++++++++++++++++-------------
     1 file changed, 34 insertions(+), 13 deletions(-)
    
    diff --git a/kernel/futex.c b/kernel/futex.c
    index 3bc18bf..66af37d 100644
    a b void exit_pi_state_list(struct task_struct *curr) 
    594594
    595595static int
    596596lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
    597                 union futex_key *key, struct futex_pi_state **ps)
     597                union futex_key *key, struct futex_pi_state **ps,
     598                struct task_struct *task)
    598599{
    599600        struct futex_pi_state *pi_state = NULL;
    600601        struct futex_q *this, *next;
    lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, 
    638639                                        return -EINVAL;
    639640                        }
    640641
     642                        /*
     643                         * Protect against a corrupted uval. If uval
     644                         * is 0x80000000 then pid is 0 and the waiter
     645                         * bit is set. So the deadlock check in the
     646                         * calling code has failed and we did not fall
     647                         * into the check above due to !pid.
     648                         */
     649                        if (task && pi_state->owner == task)
     650                                return -EDEADLK;
     651
    641652                        atomic_inc(&pi_state->refcount);
    642653                        *ps = pi_state;
    643654
    retry: 
    787798         * We dont have the lock. Look up the PI state (or create it if
    788799         * we are the first waiter):
    789800         */
    790         ret = lookup_pi_state(uval, hb, key, ps);
     801        ret = lookup_pi_state(uval, hb, key, ps, task);
    791802
    792803        if (unlikely(ret)) {
    793804                switch (ret) {
    void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key, 
    11971208 *
    11981209 * Return:
    11991210 *  0 - failed to acquire the lock atomically;
    1200  *  1 - acquired the lock;
     1211 * >0 - acquired the lock, return value is vpid of the top_waiter
    12011212 * <0 - error
    12021213 */
    12031214static int futex_proxy_trylock_atomic(u32 __user *pifutex,
    static int futex_proxy_trylock_atomic(u32 __user *pifutex, 
    12081219{
    12091220        struct futex_q *top_waiter = NULL;
    12101221        u32 curval;
    1211         int ret;
     1222        int ret, vpid;
    12121223
    12131224        if (get_futex_value_locked(&curval, pifutex))
    12141225                return -EFAULT;
    static int futex_proxy_trylock_atomic(u32 __user *pifutex, 
    12361247         * the contended case or if set_waiters is 1.  The pi_state is returned
    12371248         * in ps in contended cases.
    12381249         */
     1250        vpid = task_pid_vnr(top_waiter->task);
    12391251        ret = futex_lock_pi_atomic(pifutex, hb2, key2, ps, top_waiter->task,
    12401252                                   set_waiters);
    1241         if (ret == 1)
     1253        if (ret == 1) {
    12421254                requeue_pi_wake_futex(top_waiter, key2, hb2);
    1243 
     1255                return vpid;
     1256        }
    12441257        return ret;
    12451258}
    12461259
    static int futex_requeue(u32 __user *uaddr1, unsigned int flags, 
    12721285        struct futex_hash_bucket *hb1, *hb2;
    12731286        struct plist_head *head1;
    12741287        struct futex_q *this, *next;
    1275         u32 curval2;
    12761288
    12771289        if (requeue_pi) {
    12781290                /*
    retry_private: 
    13581370                 * At this point the top_waiter has either taken uaddr2 or is
    13591371                 * waiting on it.  If the former, then the pi_state will not
    13601372                 * exist yet, look it up one more time to ensure we have a
    1361                  * reference to it.
     1373                 * reference to it. If the lock was taken, ret contains the
     1374                 * vpid of the top waiter task.
    13621375                 */
    1363                 if (ret == 1) {
     1376                if (ret > 0) {
    13641377                        WARN_ON(pi_state);
    13651378                        drop_count++;
    13661379                        task_count++;
    1367                         ret = get_futex_value_locked(&curval2, uaddr2);
    1368                         if (!ret)
    1369                                 ret = lookup_pi_state(curval2, hb2, &key2,
    1370                                                       &pi_state);
     1380                        /*
     1381                         * If we acquired the lock, then the user
     1382                         * space value of uaddr2 should be vpid. It
     1383                         * cannot be changed by the top waiter as it
     1384                         * is blocked on hb2 lock if it tries to do
     1385                         * so. If something fiddled with it behind our
     1386                         * back the pi state lookup might unearth
     1387                         * it. So we rather use the known value than
     1388                         * rereading and handing potential crap to
     1389                         * lookup_pi_state.
     1390                         */
     1391                        ret = lookup_pi_state(ret, hb2, &key2, &pi_state, NULL);
    13711392                }
    13721393
    13731394                switch (ret) {
Note: See TracBrowser for help on using the repository browser.