diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2014-06-11 16:45:39 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2014-06-21 16:26:23 -0400 |
commit | bd1dbcc67cd2c1181e2c01daac51eabf1b964dd8 (patch) | |
tree | 96e16729f5e2247dd80cc9a3721dc8602a72bac6 /kernel/futex.c | |
parent | ccf9e6a80d9e1b9df69c98e6b9745cf49869ee15 (diff) |
futex: Use futex_top_waiter() in lookup_pi_state()
No point in open coding the same function again.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Darren Hart <darren@dvhart.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Davidlohr Bueso <davidlohr@hp.com>
Cc: Kees Cook <kees@outflux.net>
Cc: wad@chromium.org
Link: http://lkml.kernel.org/r/20140611204237.092947239@linutronix.de
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/futex.c')
-rw-r--r-- | kernel/futex.c | 124 |
1 files changed, 61 insertions, 63 deletions
diff --git a/kernel/futex.c b/kernel/futex.c index 346d5c280545..fff1ed9b1c43 100644 --- a/kernel/futex.c +++ b/kernel/futex.c | |||
@@ -796,87 +796,85 @@ static int | |||
796 | lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, | 796 | lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, |
797 | union futex_key *key, struct futex_pi_state **ps) | 797 | union futex_key *key, struct futex_pi_state **ps) |
798 | { | 798 | { |
799 | struct futex_q *match = futex_top_waiter(hb, key); | ||
799 | struct futex_pi_state *pi_state = NULL; | 800 | struct futex_pi_state *pi_state = NULL; |
800 | struct futex_q *this, *next; | ||
801 | struct task_struct *p; | 801 | struct task_struct *p; |
802 | pid_t pid = uval & FUTEX_TID_MASK; | 802 | pid_t pid = uval & FUTEX_TID_MASK; |
803 | 803 | ||
804 | plist_for_each_entry_safe(this, next, &hb->chain, list) { | 804 | if (match) { |
805 | if (match_futex(&this->key, key)) { | 805 | /* |
806 | /* | 806 | * Sanity check the waiter before increasing the |
807 | * Sanity check the waiter before increasing | 807 | * refcount and attaching to it. |
808 | * the refcount and attaching to it. | 808 | */ |
809 | */ | 809 | pi_state = match->pi_state; |
810 | pi_state = this->pi_state; | 810 | /* |
811 | /* | 811 | * Userspace might have messed up non-PI and PI |
812 | * Userspace might have messed up non-PI and | 812 | * futexes [3] |
813 | * PI futexes [3] | 813 | */ |
814 | */ | 814 | if (unlikely(!pi_state)) |
815 | if (unlikely(!pi_state)) | 815 | return -EINVAL; |
816 | return -EINVAL; | ||
817 | 816 | ||
818 | WARN_ON(!atomic_read(&pi_state->refcount)); | 817 | WARN_ON(!atomic_read(&pi_state->refcount)); |
819 | 818 | ||
819 | /* | ||
820 | * Handle the owner died case: | ||
821 | */ | ||
822 | if (uval & FUTEX_OWNER_DIED) { | ||
820 | /* | 823 | /* |
821 | * Handle the owner died case: | 824 | * exit_pi_state_list sets owner to NULL and |
825 | * wakes the topmost waiter. The task which | ||
826 | * acquires the pi_state->rt_mutex will fixup | ||
827 | * owner. | ||
822 | */ | 828 | */ |
823 | if (uval & FUTEX_OWNER_DIED) { | 829 | if (!pi_state->owner) { |
824 | /* | 830 | /* |
825 | * exit_pi_state_list sets owner to NULL and | 831 | * No pi state owner, but the user |
826 | * wakes the topmost waiter. The task which | 832 | * space TID is not 0. Inconsistent |
827 | * acquires the pi_state->rt_mutex will fixup | 833 | * state. [5] |
828 | * owner. | ||
829 | */ | 834 | */ |
830 | if (!pi_state->owner) { | 835 | if (pid) |
831 | /* | 836 | return -EINVAL; |
832 | * No pi state owner, but the user | ||
833 | * space TID is not 0. Inconsistent | ||
834 | * state. [5] | ||
835 | */ | ||
836 | if (pid) | ||
837 | return -EINVAL; | ||
838 | /* | ||
839 | * Take a ref on the state and | ||
840 | * return. [4] | ||
841 | */ | ||
842 | goto out_state; | ||
843 | } | ||
844 | |||
845 | /* | ||
846 | * If TID is 0, then either the dying owner | ||
847 | * has not yet executed exit_pi_state_list() | ||
848 | * or some waiter acquired the rtmutex in the | ||
849 | * pi state, but did not yet fixup the TID in | ||
850 | * user space. | ||
851 | * | ||
852 | * Take a ref on the state and return. [6] | ||
853 | */ | ||
854 | if (!pid) | ||
855 | goto out_state; | ||
856 | } else { | ||
857 | /* | 837 | /* |
858 | * If the owner died bit is not set, | 838 | * Take a ref on the state and |
859 | * then the pi_state must have an | 839 | * return. [4] |
860 | * owner. [7] | ||
861 | */ | 840 | */ |
862 | if (!pi_state->owner) | 841 | goto out_state; |
863 | return -EINVAL; | ||
864 | } | 842 | } |
865 | 843 | ||
866 | /* | 844 | /* |
867 | * Bail out if user space manipulated the | 845 | * If TID is 0, then either the dying owner |
868 | * futex value. If pi state exists then the | 846 | * has not yet executed exit_pi_state_list() |
869 | * owner TID must be the same as the user | 847 | * or some waiter acquired the rtmutex in the |
870 | * space TID. [9/10] | 848 | * pi state, but did not yet fixup the TID in |
849 | * user space. | ||
850 | * | ||
851 | * Take a ref on the state and return. [6] | ||
852 | */ | ||
853 | if (!pid) | ||
854 | goto out_state; | ||
855 | } else { | ||
856 | /* | ||
857 | * If the owner died bit is not set, | ||
858 | * then the pi_state must have an | ||
859 | * owner. [7] | ||
871 | */ | 860 | */ |
872 | if (pid != task_pid_vnr(pi_state->owner)) | 861 | if (!pi_state->owner) |
873 | return -EINVAL; | 862 | return -EINVAL; |
874 | |||
875 | out_state: | ||
876 | atomic_inc(&pi_state->refcount); | ||
877 | *ps = pi_state; | ||
878 | return 0; | ||
879 | } | 863 | } |
864 | |||
865 | /* | ||
866 | * Bail out if user space manipulated the | ||
867 | * futex value. If pi state exists then the | ||
868 | * owner TID must be the same as the user | ||
869 | * space TID. [9/10] | ||
870 | */ | ||
871 | if (pid != task_pid_vnr(pi_state->owner)) | ||
872 | return -EINVAL; | ||
873 | |||
874 | out_state: | ||
875 | atomic_inc(&pi_state->refcount); | ||
876 | *ps = pi_state; | ||
877 | return 0; | ||
880 | } | 878 | } |
881 | 879 | ||
882 | /* | 880 | /* |