diff options
Diffstat (limited to 'kernel/futex.c')
| -rw-r--r-- | kernel/futex.c | 89 |
1 files changed, 38 insertions, 51 deletions
diff --git a/kernel/futex.c b/kernel/futex.c index 1614be20173d..e2b0fb9a0b3b 100644 --- a/kernel/futex.c +++ b/kernel/futex.c | |||
| @@ -59,6 +59,7 @@ | |||
| 59 | #include <linux/magic.h> | 59 | #include <linux/magic.h> |
| 60 | #include <linux/pid.h> | 60 | #include <linux/pid.h> |
| 61 | #include <linux/nsproxy.h> | 61 | #include <linux/nsproxy.h> |
| 62 | #include <linux/ptrace.h> | ||
| 62 | 63 | ||
| 63 | #include <asm/futex.h> | 64 | #include <asm/futex.h> |
| 64 | 65 | ||
| @@ -2443,40 +2444,31 @@ SYSCALL_DEFINE3(get_robust_list, int, pid, | |||
| 2443 | { | 2444 | { |
| 2444 | struct robust_list_head __user *head; | 2445 | struct robust_list_head __user *head; |
| 2445 | unsigned long ret; | 2446 | unsigned long ret; |
| 2446 | const struct cred *cred = current_cred(), *pcred; | 2447 | struct task_struct *p; |
| 2447 | 2448 | ||
| 2448 | if (!futex_cmpxchg_enabled) | 2449 | if (!futex_cmpxchg_enabled) |
| 2449 | return -ENOSYS; | 2450 | return -ENOSYS; |
| 2450 | 2451 | ||
| 2452 | WARN_ONCE(1, "deprecated: get_robust_list will be deleted in 2013.\n"); | ||
| 2453 | |||
| 2454 | rcu_read_lock(); | ||
| 2455 | |||
| 2456 | ret = -ESRCH; | ||
| 2451 | if (!pid) | 2457 | if (!pid) |
| 2452 | head = current->robust_list; | 2458 | p = current; |
| 2453 | else { | 2459 | else { |
| 2454 | struct task_struct *p; | ||
| 2455 | |||
| 2456 | ret = -ESRCH; | ||
| 2457 | rcu_read_lock(); | ||
| 2458 | p = find_task_by_vpid(pid); | 2460 | p = find_task_by_vpid(pid); |
| 2459 | if (!p) | 2461 | if (!p) |
| 2460 | goto err_unlock; | 2462 | goto err_unlock; |
| 2461 | ret = -EPERM; | ||
| 2462 | pcred = __task_cred(p); | ||
| 2463 | /* If victim is in different user_ns, then uids are not | ||
| 2464 | comparable, so we must have CAP_SYS_PTRACE */ | ||
| 2465 | if (cred->user->user_ns != pcred->user->user_ns) { | ||
| 2466 | if (!ns_capable(pcred->user->user_ns, CAP_SYS_PTRACE)) | ||
| 2467 | goto err_unlock; | ||
| 2468 | goto ok; | ||
| 2469 | } | ||
| 2470 | /* If victim is in same user_ns, then uids are comparable */ | ||
| 2471 | if (cred->euid != pcred->euid && | ||
| 2472 | cred->euid != pcred->uid && | ||
| 2473 | !ns_capable(pcred->user->user_ns, CAP_SYS_PTRACE)) | ||
| 2474 | goto err_unlock; | ||
| 2475 | ok: | ||
| 2476 | head = p->robust_list; | ||
| 2477 | rcu_read_unlock(); | ||
| 2478 | } | 2463 | } |
| 2479 | 2464 | ||
| 2465 | ret = -EPERM; | ||
| 2466 | if (!ptrace_may_access(p, PTRACE_MODE_READ)) | ||
| 2467 | goto err_unlock; | ||
| 2468 | |||
| 2469 | head = p->robust_list; | ||
| 2470 | rcu_read_unlock(); | ||
| 2471 | |||
| 2480 | if (put_user(sizeof(*head), len_ptr)) | 2472 | if (put_user(sizeof(*head), len_ptr)) |
| 2481 | return -EFAULT; | 2473 | return -EFAULT; |
| 2482 | return put_user(head, head_ptr); | 2474 | return put_user(head, head_ptr); |
| @@ -2628,7 +2620,7 @@ void exit_robust_list(struct task_struct *curr) | |||
| 2628 | long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout, | 2620 | long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout, |
| 2629 | u32 __user *uaddr2, u32 val2, u32 val3) | 2621 | u32 __user *uaddr2, u32 val2, u32 val3) |
| 2630 | { | 2622 | { |
| 2631 | int ret = -ENOSYS, cmd = op & FUTEX_CMD_MASK; | 2623 | int cmd = op & FUTEX_CMD_MASK; |
| 2632 | unsigned int flags = 0; | 2624 | unsigned int flags = 0; |
| 2633 | 2625 | ||
| 2634 | if (!(op & FUTEX_PRIVATE_FLAG)) | 2626 | if (!(op & FUTEX_PRIVATE_FLAG)) |
| @@ -2641,49 +2633,44 @@ long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout, | |||
| 2641 | } | 2633 | } |
| 2642 | 2634 | ||
| 2643 | switch (cmd) { | 2635 | switch (cmd) { |
| 2636 | case FUTEX_LOCK_PI: | ||
| 2637 | case FUTEX_UNLOCK_PI: | ||
| 2638 | case FUTEX_TRYLOCK_PI: | ||
| 2639 | case FUTEX_WAIT_REQUEUE_PI: | ||
| 2640 | case FUTEX_CMP_REQUEUE_PI: | ||
| 2641 | if (!futex_cmpxchg_enabled) | ||
| 2642 | return -ENOSYS; | ||
| 2643 | } | ||
| 2644 | |||
| 2645 | switch (cmd) { | ||
| 2644 | case FUTEX_WAIT: | 2646 | case FUTEX_WAIT: |
| 2645 | val3 = FUTEX_BITSET_MATCH_ANY; | 2647 | val3 = FUTEX_BITSET_MATCH_ANY; |
| 2646 | case FUTEX_WAIT_BITSET: | 2648 | case FUTEX_WAIT_BITSET: |
| 2647 | ret = futex_wait(uaddr, flags, val, timeout, val3); | 2649 | return futex_wait(uaddr, flags, val, timeout, val3); |
| 2648 | break; | ||
| 2649 | case FUTEX_WAKE: | 2650 | case FUTEX_WAKE: |
| 2650 | val3 = FUTEX_BITSET_MATCH_ANY; | 2651 | val3 = FUTEX_BITSET_MATCH_ANY; |
| 2651 | case FUTEX_WAKE_BITSET: | 2652 | case FUTEX_WAKE_BITSET: |
| 2652 | ret = futex_wake(uaddr, flags, val, val3); | 2653 | return futex_wake(uaddr, flags, val, val3); |
| 2653 | break; | ||
| 2654 | case FUTEX_REQUEUE: | 2654 | case FUTEX_REQUEUE: |
| 2655 | ret = futex_requeue(uaddr, flags, uaddr2, val, val2, NULL, 0); | 2655 | return futex_requeue(uaddr, flags, uaddr2, val, val2, NULL, 0); |
| 2656 | break; | ||
| 2657 | case FUTEX_CMP_REQUEUE: | 2656 | case FUTEX_CMP_REQUEUE: |
| 2658 | ret = futex_requeue(uaddr, flags, uaddr2, val, val2, &val3, 0); | 2657 | return futex_requeue(uaddr, flags, uaddr2, val, val2, &val3, 0); |
| 2659 | break; | ||
| 2660 | case FUTEX_WAKE_OP: | 2658 | case FUTEX_WAKE_OP: |
| 2661 | ret = futex_wake_op(uaddr, flags, uaddr2, val, val2, val3); | 2659 | return futex_wake_op(uaddr, flags, uaddr2, val, val2, val3); |
| 2662 | break; | ||
| 2663 | case FUTEX_LOCK_PI: | 2660 | case FUTEX_LOCK_PI: |
| 2664 | if (futex_cmpxchg_enabled) | 2661 | return futex_lock_pi(uaddr, flags, val, timeout, 0); |
| 2665 | ret = futex_lock_pi(uaddr, flags, val, timeout, 0); | ||
| 2666 | break; | ||
| 2667 | case FUTEX_UNLOCK_PI: | 2662 | case FUTEX_UNLOCK_PI: |
| 2668 | if (futex_cmpxchg_enabled) | 2663 | return futex_unlock_pi(uaddr, flags); |
| 2669 | ret = futex_unlock_pi(uaddr, flags); | ||
| 2670 | break; | ||
| 2671 | case FUTEX_TRYLOCK_PI: | 2664 | case FUTEX_TRYLOCK_PI: |
| 2672 | if (futex_cmpxchg_enabled) | 2665 | return futex_lock_pi(uaddr, flags, 0, timeout, 1); |
| 2673 | ret = futex_lock_pi(uaddr, flags, 0, timeout, 1); | ||
| 2674 | break; | ||
| 2675 | case FUTEX_WAIT_REQUEUE_PI: | 2666 | case FUTEX_WAIT_REQUEUE_PI: |
| 2676 | val3 = FUTEX_BITSET_MATCH_ANY; | 2667 | val3 = FUTEX_BITSET_MATCH_ANY; |
| 2677 | ret = futex_wait_requeue_pi(uaddr, flags, val, timeout, val3, | 2668 | return futex_wait_requeue_pi(uaddr, flags, val, timeout, val3, |
| 2678 | uaddr2); | 2669 | uaddr2); |
| 2679 | break; | ||
| 2680 | case FUTEX_CMP_REQUEUE_PI: | 2670 | case FUTEX_CMP_REQUEUE_PI: |
| 2681 | ret = futex_requeue(uaddr, flags, uaddr2, val, val2, &val3, 1); | 2671 | return futex_requeue(uaddr, flags, uaddr2, val, val2, &val3, 1); |
| 2682 | break; | ||
| 2683 | default: | ||
| 2684 | ret = -ENOSYS; | ||
| 2685 | } | 2672 | } |
| 2686 | return ret; | 2673 | return -ENOSYS; |
| 2687 | } | 2674 | } |
| 2688 | 2675 | ||
| 2689 | 2676 | ||
