Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull core futex/rtmutex fixes from Thomas Gleixner:
"Three fixlets for long standing issues in the futex/rtmutex code
unearthed by Dave Jones syscall fuzzer:

- Add missing early deadlock detection checks in the futex code
- Prevent user space from attaching a futex to kernel threads
- Make the deadlock detector of rtmutex work again

Looks large, but is more comments than code change"

* 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
rtmutex: Fix deadlock detector for real
futex: Prevent attaching to kernel threads
futex: Add another early deadlock detection check

+67 -17
+39 -13
kernel/futex.c
··· 745 745 746 746 static int 747 747 lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, 748 - union futex_key *key, struct futex_pi_state **ps) 748 + union futex_key *key, struct futex_pi_state **ps, 749 + struct task_struct *task) 749 750 { 750 751 struct futex_pi_state *pi_state = NULL; 751 752 struct futex_q *this, *next; ··· 787 786 return -EINVAL; 788 787 } 789 788 789 + /* 790 + * Protect against a corrupted uval. If uval 791 + * is 0x80000000 then pid is 0 and the waiter 792 + * bit is set. So the deadlock check in the 793 + * calling code has failed and we did not fall 794 + * into the check above due to !pid. 795 + */ 796 + if (task && pi_state->owner == task) 797 + return -EDEADLK; 798 + 790 799 atomic_inc(&pi_state->refcount); 791 800 *ps = pi_state; 792 801 ··· 813 802 p = futex_find_get_task(pid); 814 803 if (!p) 815 804 return -ESRCH; 805 + 806 + if (!p->mm) { 807 + put_task_struct(p); 808 + return -EPERM; 809 + } 816 810 817 811 /* 818 812 * We need to look at the task state flags to figure out, ··· 951 935 * We dont have the lock. Look up the PI state (or create it if 952 936 * we are the first waiter): 953 937 */ 954 - ret = lookup_pi_state(uval, hb, key, ps); 938 + ret = lookup_pi_state(uval, hb, key, ps, task); 955 939 956 940 if (unlikely(ret)) { 957 941 switch (ret) { ··· 1363 1347 * 1364 1348 * Return: 1365 1349 * 0 - failed to acquire the lock atomically; 1366 - * 1 - acquired the lock; 1350 + * >0 - acquired the lock, return value is vpid of the top_waiter 1367 1351 * <0 - error 1368 1352 */ 1369 1353 static int futex_proxy_trylock_atomic(u32 __user *pifutex, ··· 1374 1358 { 1375 1359 struct futex_q *top_waiter = NULL; 1376 1360 u32 curval; 1377 - int ret; 1361 + int ret, vpid; 1378 1362 1379 1363 if (get_futex_value_locked(&curval, pifutex)) 1380 1364 return -EFAULT; ··· 1402 1386 * the contended case or if set_waiters is 1. The pi_state is returned 1403 1387 * in ps in contended cases. 1404 1388 */ 1389 + vpid = task_pid_vnr(top_waiter->task); 1405 1390 ret = futex_lock_pi_atomic(pifutex, hb2, key2, ps, top_waiter->task, 1406 1391 set_waiters); 1407 - if (ret == 1) 1392 + if (ret == 1) { 1408 1393 requeue_pi_wake_futex(top_waiter, key2, hb2); 1409 - 1394 + return vpid; 1395 + } 1410 1396 return ret; 1411 1397 } 1412 1398 ··· 1439 1421 struct futex_pi_state *pi_state = NULL; 1440 1422 struct futex_hash_bucket *hb1, *hb2; 1441 1423 struct futex_q *this, *next; 1442 - u32 curval2; 1443 1424 1444 1425 if (requeue_pi) { 1445 1426 /* ··· 1526 1509 * At this point the top_waiter has either taken uaddr2 or is 1527 1510 * waiting on it. If the former, then the pi_state will not 1528 1511 * exist yet, look it up one more time to ensure we have a 1529 - * reference to it. 1512 + * reference to it. If the lock was taken, ret contains the 1513 + * vpid of the top waiter task. 1530 1514 */ 1531 - if (ret == 1) { 1515 + if (ret > 0) { 1532 1516 WARN_ON(pi_state); 1533 1517 drop_count++; 1534 1518 task_count++; 1535 - ret = get_futex_value_locked(&curval2, uaddr2); 1536 - if (!ret) 1537 - ret = lookup_pi_state(curval2, hb2, &key2, 1538 - &pi_state); 1519 + /* 1520 + * If we acquired the lock, then the user 1521 + * space value of uaddr2 should be vpid. It 1522 + * cannot be changed by the top waiter as it 1523 + * is blocked on hb2 lock if it tries to do 1524 + * so. If something fiddled with it behind our 1525 + * back the pi state lookup might unearth 1526 + * it. So we rather use the known value than 1527 + * rereading and handing potential crap to 1528 + * lookup_pi_state. 1529 + */ 1530 + ret = lookup_pi_state(ret, hb2, &key2, &pi_state, NULL); 1539 1531 } 1540 1532 1541 1533 switch (ret) {
+28 -4
kernel/locking/rtmutex.c
··· 343 343 * top_waiter can be NULL, when we are in the deboosting 344 344 * mode! 345 345 */ 346 - if (top_waiter && (!task_has_pi_waiters(task) || 347 - top_waiter != task_top_pi_waiter(task))) 348 - goto out_unlock_pi; 346 + if (top_waiter) { 347 + if (!task_has_pi_waiters(task)) 348 + goto out_unlock_pi; 349 + /* 350 + * If deadlock detection is off, we stop here if we 351 + * are not the top pi waiter of the task. 352 + */ 353 + if (!detect_deadlock && top_waiter != task_top_pi_waiter(task)) 354 + goto out_unlock_pi; 355 + } 349 356 350 357 /* 351 358 * When deadlock detection is off then we check, if further ··· 368 361 goto retry; 369 362 } 370 363 371 - /* Deadlock detection */ 364 + /* 365 + * Deadlock detection. If the lock is the same as the original 366 + * lock which caused us to walk the lock chain or if the 367 + * current lock is owned by the task which initiated the chain 368 + * walk, we detected a deadlock. 369 + */ 372 370 if (lock == orig_lock || rt_mutex_owner(lock) == top_task) { 373 371 debug_rt_mutex_deadlock(deadlock_detect, orig_waiter, lock); 374 372 raw_spin_unlock(&lock->wait_lock); ··· 538 526 struct rt_mutex_waiter *top_waiter = waiter; 539 527 unsigned long flags; 540 528 int chain_walk = 0, res; 529 + 530 + /* 531 + * Early deadlock detection. We really don't want the task to 532 + * enqueue on itself just to untangle the mess later. It's not 533 + * only an optimization. We drop the locks, so another waiter 534 + * can come in before the chain walk detects the deadlock. So 535 + * the other will detect the deadlock and return -EDEADLOCK, 536 + * which is wrong, as the other waiter is not in a deadlock 537 + * situation. 538 + */ 539 + if (detect_deadlock && owner == task) 540 + return -EDEADLK; 541 541 542 542 raw_spin_lock_irqsave(&task->pi_lock, flags); 543 543 __rt_mutex_adjust_prio(task);