Commit e9c243a5a6de0be8e584c604d353412584b592f8
Committed by
Linus Torvalds
1 parent
fad01e866a
Exists in
ti-lsk-linux-4.1.y
and in
12 other branches
futex-prevent-requeue-pi-on-same-futex.patch futex: Forbid uaddr == uaddr2 in fu…
…tex_requeue(..., requeue_pi=1) 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> Cc: stable@vger.kernel.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>
Showing 1 changed file with 25 additions and 0 deletions Side-by-side Diff
kernel/futex.c
... | ... | @@ -1442,6 +1442,13 @@ |
1442 | 1442 | |
1443 | 1443 | if (requeue_pi) { |
1444 | 1444 | /* |
1445 | + * Requeue PI only works on two distinct uaddrs. This | |
1446 | + * check is only valid for private futexes. See below. | |
1447 | + */ | |
1448 | + if (uaddr1 == uaddr2) | |
1449 | + return -EINVAL; | |
1450 | + | |
1451 | + /* | |
1445 | 1452 | * requeue_pi requires a pi_state, try to allocate it now |
1446 | 1453 | * without any locks in case it fails. |
1447 | 1454 | */ |
... | ... | @@ -1479,6 +1486,15 @@ |
1479 | 1486 | if (unlikely(ret != 0)) |
1480 | 1487 | goto out_put_key1; |
1481 | 1488 | |
1489 | + /* | |
1490 | + * The check above which compares uaddrs is not sufficient for | |
1491 | + * shared futexes. We need to compare the keys: | |
1492 | + */ | |
1493 | + if (requeue_pi && match_futex(&key1, &key2)) { | |
1494 | + ret = -EINVAL; | |
1495 | + goto out_put_keys; | |
1496 | + } | |
1497 | + | |
1482 | 1498 | hb1 = hash_futex(&key1); |
1483 | 1499 | hb2 = hash_futex(&key2); |
1484 | 1500 | |
... | ... | @@ -2524,6 +2540,15 @@ |
2524 | 2540 | ret = futex_wait_setup(uaddr, val, flags, &q, &hb); |
2525 | 2541 | if (ret) |
2526 | 2542 | goto out_key2; |
2543 | + | |
2544 | + /* | |
2545 | + * The check above which compares uaddrs is not sufficient for | |
2546 | + * shared futexes. We need to compare the keys: | |
2547 | + */ | |
2548 | + if (match_futex(&q.key, &key2)) { | |
2549 | + ret = -EINVAL; | |
2550 | + goto out_put_keys; | |
2551 | + } | |
2527 | 2552 | |
2528 | 2553 | /* Queue the futex_q, drop the hb lock, wait for wakeup. */ |
2529 | 2554 | futex_wait_queue_me(hb, &q, to); |