|
@@ -38,10 +38,11 @@ fetch_robust_entry(compat_uptr_t *uentry, struct robust_list __user **entry,
|
|
|
void compat_exit_robust_list(struct task_struct *curr)
|
|
|
{
|
|
|
struct compat_robust_list_head __user *head = curr->compat_robust_list;
|
|
|
- struct robust_list __user *entry, *pending;
|
|
|
- unsigned int limit = ROBUST_LIST_LIMIT, pi, pip;
|
|
|
- compat_uptr_t uentry, upending;
|
|
|
+ struct robust_list __user *entry, *next_entry, *pending;
|
|
|
+ unsigned int limit = ROBUST_LIST_LIMIT, pi, next_pi, pip;
|
|
|
+ compat_uptr_t uentry, next_uentry, upending;
|
|
|
compat_long_t futex_offset;
|
|
|
+ int rc;
|
|
|
|
|
|
/*
|
|
|
* Fetch the list head (which was registered earlier, via
|
|
@@ -61,10 +62,15 @@ void compat_exit_robust_list(struct task_struct *curr)
|
|
|
if (fetch_robust_entry(&upending, &pending,
|
|
|
&head->list_op_pending, &pip))
|
|
|
return;
|
|
|
- if (pending)
|
|
|
- handle_futex_death((void __user *)pending + futex_offset, curr, pip);
|
|
|
|
|
|
+ next_entry = NULL; /* avoid warning with gcc */
|
|
|
while (entry != (struct robust_list __user *) &head->list) {
|
|
|
+ /*
|
|
|
+ * Fetch the next entry in the list before calling
|
|
|
+ * handle_futex_death:
|
|
|
+ */
|
|
|
+ rc = fetch_robust_entry(&next_uentry, &next_entry,
|
|
|
+ (compat_uptr_t __user *)&entry->next, &next_pi);
|
|
|
/*
|
|
|
* A pending lock might already be on the list, so
|
|
|
* dont process it twice:
|
|
@@ -74,12 +80,11 @@ void compat_exit_robust_list(struct task_struct *curr)
|
|
|
curr, pi))
|
|
|
return;
|
|
|
|
|
|
- /*
|
|
|
- * Fetch the next entry in the list:
|
|
|
- */
|
|
|
- if (fetch_robust_entry(&uentry, &entry,
|
|
|
- (compat_uptr_t __user *)&entry->next, &pi))
|
|
|
+ if (rc)
|
|
|
return;
|
|
|
+ uentry = next_uentry;
|
|
|
+ entry = next_entry;
|
|
|
+ pi = next_pi;
|
|
|
/*
|
|
|
* Avoid excessively long or circular lists:
|
|
|
*/
|
|
@@ -88,6 +93,9 @@ void compat_exit_robust_list(struct task_struct *curr)
|
|
|
|
|
|
cond_resched();
|
|
|
}
|
|
|
+ if (pending)
|
|
|
+ handle_futex_death((void __user *)pending + futex_offset,
|
|
|
+ curr, pip);
|
|
|
}
|
|
|
|
|
|
asmlinkage long
|