lkml.org 
[lkml]   [2014]   [Jun]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.13 206/212] futex-prevent-requeue-pi-on-same-futex.patch futex: Forbid uaddr == uaddr2 in futex_requeue(..., requeue_pi=1)
    Date
    3.13.11.4 -stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Thomas Gleixner <tglx@linutronix.de>

    commit e9c243a5a6de0be8e584c604d353412584b592f8 upstream.

    If uaddr == uaddr2, then we have broken the rule of only requeueing from
    a non-pi futex to a pi futex with this call. If we attempt this, then
    dangling pointers may be left for rt_waiter resulting in an exploitable
    condition.

    This change brings futex_requeue() in line with futex_wait_requeue_pi()
    which performs the same check as per commit 6f7b0a2a5c0f ("futex: Forbid
    uaddr == uaddr2 in futex_wait_requeue_pi()")

    [ tglx: Compare the resulting keys as well, as uaddrs might be
    different depending on the mapping ]

    Fixes CVE-2014-3153.

    Reported-by: Pinkie Pie
    Signed-off-by: Will Drewry <wad@chromium.org>
    Signed-off-by: Kees Cook <keescook@chromium.org>
    Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
    Reviewed-by: Darren Hart <dvhart@linux.intel.com>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
    Signed-off-by: Kamal Mostafa <kamal@canonical.com>
    ---
    kernel/futex.c | 25 +++++++++++++++++++++++++
    1 file changed, 25 insertions(+)

    diff --git a/kernel/futex.c b/kernel/futex.c
    index 7876c15..c861191 100644
    --- a/kernel/futex.c
    +++ b/kernel/futex.c
    @@ -1295,6 +1295,13 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,

    if (requeue_pi) {
    /*
    + * Requeue PI only works on two distinct uaddrs. This
    + * check is only valid for private futexes. See below.
    + */
    + if (uaddr1 == uaddr2)
    + return -EINVAL;
    +
    + /*
    * requeue_pi requires a pi_state, try to allocate it now
    * without any locks in case it fails.
    */
    @@ -1332,6 +1339,15 @@ retry:
    if (unlikely(ret != 0))
    goto out_put_key1;

    + /*
    + * The check above which compares uaddrs is not sufficient for
    + * shared futexes. We need to compare the keys:
    + */
    + if (requeue_pi && match_futex(&key1, &key2)) {
    + ret = -EINVAL;
    + goto out_put_keys;
    + }
    +
    hb1 = hash_futex(&key1);
    hb2 = hash_futex(&key2);

    @@ -2362,6 +2378,15 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
    if (ret)
    goto out_key2;

    + /*
    + * The check above which compares uaddrs is not sufficient for
    + * shared futexes. We need to compare the keys:
    + */
    + if (match_futex(&q.key, &key2)) {
    + ret = -EINVAL;
    + goto out_put_keys;
    + }
    +
    /* Queue the futex_q, drop the hb lock, wait for wakeup. */
    futex_wait_queue_me(hb, &q, to);

    --
    1.9.1


    \
     
     \ /
      Last update: 2014-06-18 01:01    [W:4.185 / U:0.160 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site