aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/futex.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/futex.c')
-rw-r--r--kernel/futex.c134
1 files changed, 106 insertions, 28 deletions
diff --git a/kernel/futex.c b/kernel/futex.c
index e1cb1baa23fb..de938d20df19 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -743,10 +743,58 @@ void exit_pi_state_list(struct task_struct *curr)
743 raw_spin_unlock_irq(&curr->pi_lock); 743 raw_spin_unlock_irq(&curr->pi_lock);
744} 744}
745 745
746/*
747 * We need to check the following states:
748 *
749 * Waiter | pi_state | pi->owner | uTID | uODIED | ?
750 *
751 * [1] NULL | --- | --- | 0 | 0/1 | Valid
752 * [2] NULL | --- | --- | >0 | 0/1 | Valid
753 *
754 * [3] Found | NULL | -- | Any | 0/1 | Invalid
755 *
756 * [4] Found | Found | NULL | 0 | 1 | Valid
757 * [5] Found | Found | NULL | >0 | 1 | Invalid
758 *
759 * [6] Found | Found | task | 0 | 1 | Valid
760 *
761 * [7] Found | Found | NULL | Any | 0 | Invalid
762 *
763 * [8] Found | Found | task | ==taskTID | 0/1 | Valid
764 * [9] Found | Found | task | 0 | 0 | Invalid
765 * [10] Found | Found | task | !=taskTID | 0/1 | Invalid
766 *
767 * [1] Indicates that the kernel can acquire the futex atomically. We
768 * came came here due to a stale FUTEX_WAITERS/FUTEX_OWNER_DIED bit.
769 *
770 * [2] Valid, if TID does not belong to a kernel thread. If no matching
771 * thread is found then it indicates that the owner TID has died.
772 *
773 * [3] Invalid. The waiter is queued on a non PI futex
774 *
775 * [4] Valid state after exit_robust_list(), which sets the user space
776 * value to FUTEX_WAITERS | FUTEX_OWNER_DIED.
777 *
778 * [5] The user space value got manipulated between exit_robust_list()
779 * and exit_pi_state_list()
780 *
781 * [6] Valid state after exit_pi_state_list() which sets the new owner in
782 * the pi_state but cannot access the user space value.
783 *
784 * [7] pi_state->owner can only be NULL when the OWNER_DIED bit is set.
785 *
786 * [8] Owner and user space value match
787 *
788 * [9] There is no transient state which sets the user space TID to 0
789 * except exit_robust_list(), but this is indicated by the
790 * FUTEX_OWNER_DIED bit. See [4]
791 *
792 * [10] There is no transient state which leaves owner and user space
793 * TID out of sync.
794 */
746static int 795static int
747lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, 796lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
748 union futex_key *key, struct futex_pi_state **ps, 797 union futex_key *key, struct futex_pi_state **ps)
749 struct task_struct *task)
750{ 798{
751 struct futex_pi_state *pi_state = NULL; 799 struct futex_pi_state *pi_state = NULL;
752 struct futex_q *this, *next; 800 struct futex_q *this, *next;
@@ -756,12 +804,13 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
756 plist_for_each_entry_safe(this, next, &hb->chain, list) { 804 plist_for_each_entry_safe(this, next, &hb->chain, list) {
757 if (match_futex(&this->key, key)) { 805 if (match_futex(&this->key, key)) {
758 /* 806 /*
759 * Another waiter already exists - bump up 807 * Sanity check the waiter before increasing
760 * the refcount and return its pi_state: 808 * the refcount and attaching to it.
761 */ 809 */
762 pi_state = this->pi_state; 810 pi_state = this->pi_state;
763 /* 811 /*
764 * Userspace might have messed up non-PI and PI futexes 812 * Userspace might have messed up non-PI and
813 * PI futexes [3]
765 */ 814 */
766 if (unlikely(!pi_state)) 815 if (unlikely(!pi_state))
767 return -EINVAL; 816 return -EINVAL;
@@ -769,44 +818,70 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
769 WARN_ON(!atomic_read(&pi_state->refcount)); 818 WARN_ON(!atomic_read(&pi_state->refcount));
770 819
771 /* 820 /*
772 * When pi_state->owner is NULL then the owner died 821 * Handle the owner died case:
773 * and another waiter is on the fly. pi_state->owner
774 * is fixed up by the task which acquires
775 * pi_state->rt_mutex.
776 *
777 * We do not check for pid == 0 which can happen when
778 * the owner died and robust_list_exit() cleared the
779 * TID.
780 */ 822 */
781 if (pid && pi_state->owner) { 823 if (uval & FUTEX_OWNER_DIED) {
782 /* 824 /*
783 * Bail out if user space manipulated the 825 * exit_pi_state_list sets owner to NULL and
784 * futex value. 826 * wakes the topmost waiter. The task which
827 * acquires the pi_state->rt_mutex will fixup
828 * owner.
785 */ 829 */
786 if (pid != task_pid_vnr(pi_state->owner)) 830 if (!pi_state->owner) {
831 /*
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 /*
858 * If the owner died bit is not set,
859 * then the pi_state must have an
860 * owner. [7]
861 */
862 if (!pi_state->owner)
787 return -EINVAL; 863 return -EINVAL;
788 } 864 }
789 865
790 /* 866 /*
791 * Protect against a corrupted uval. If uval 867 * Bail out if user space manipulated the
792 * is 0x80000000 then pid is 0 and the waiter 868 * futex value. If pi state exists then the
793 * bit is set. So the deadlock check in the 869 * owner TID must be the same as the user
794 * calling code has failed and we did not fall 870 * space TID. [9/10]
795 * into the check above due to !pid.
796 */ 871 */
797 if (task && pi_state->owner == task) 872 if (pid != task_pid_vnr(pi_state->owner))
798 return -EDEADLK; 873 return -EINVAL;
799 874
875 out_state:
800 atomic_inc(&pi_state->refcount); 876 atomic_inc(&pi_state->refcount);
801 *ps = pi_state; 877 *ps = pi_state;
802
803 return 0; 878 return 0;
804 } 879 }
805 } 880 }
806 881
807 /* 882 /*
808 * We are the first waiter - try to look up the real owner and attach 883 * We are the first waiter - try to look up the real owner and attach
809 * the new pi_state to it, but bail out when TID = 0 884 * the new pi_state to it, but bail out when TID = 0 [1]
810 */ 885 */
811 if (!pid) 886 if (!pid)
812 return -ESRCH; 887 return -ESRCH;
@@ -839,6 +914,9 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
839 return ret; 914 return ret;
840 } 915 }
841 916
917 /*
918 * No existing pi state. First waiter. [2]
919 */
842 pi_state = alloc_pi_state(); 920 pi_state = alloc_pi_state();
843 921
844 /* 922 /*
@@ -959,7 +1037,7 @@ retry:
959 * We dont have the lock. Look up the PI state (or create it if 1037 * We dont have the lock. Look up the PI state (or create it if
960 * we are the first waiter): 1038 * we are the first waiter):
961 */ 1039 */
962 ret = lookup_pi_state(uval, hb, key, ps, task); 1040 ret = lookup_pi_state(uval, hb, key, ps);
963 1041
964 if (unlikely(ret)) { 1042 if (unlikely(ret)) {
965 switch (ret) { 1043 switch (ret) {
@@ -1565,7 +1643,7 @@ retry_private:
1565 * rereading and handing potential crap to 1643 * rereading and handing potential crap to
1566 * lookup_pi_state. 1644 * lookup_pi_state.
1567 */ 1645 */
1568 ret = lookup_pi_state(ret, hb2, &key2, &pi_state, NULL); 1646 ret = lookup_pi_state(ret, hb2, &key2, &pi_state);
1569 } 1647 }
1570 1648
1571 switch (ret) { 1649 switch (ret) {