diff options
Diffstat (limited to 'kernel/futex.c')
-rw-r--r-- | kernel/futex.c | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/kernel/futex.c b/kernel/futex.c index c6bef6e404fe..e9251d934f7d 100644 --- a/kernel/futex.c +++ b/kernel/futex.c | |||
@@ -2458,9 +2458,20 @@ retry: | |||
2458 | * userspace. | 2458 | * userspace. |
2459 | */ | 2459 | */ |
2460 | mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED; | 2460 | mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED; |
2461 | if (futex_atomic_cmpxchg_inatomic(&nval, uaddr, uval, mval)) | 2461 | /* |
2462 | return -1; | 2462 | * We are not holding a lock here, but we want to have |
2463 | 2463 | * the pagefault_disable/enable() protection because | |
2464 | * we want to handle the fault gracefully. If the | ||
2465 | * access fails we try to fault in the futex with R/W | ||
2466 | * verification via get_user_pages. get_user() above | ||
2467 | * does not guarantee R/W access. If that fails we | ||
2468 | * give up and leave the futex locked. | ||
2469 | */ | ||
2470 | if (cmpxchg_futex_value_locked(&nval, uaddr, uval, mval)) { | ||
2471 | if (fault_in_user_writeable(uaddr)) | ||
2472 | return -1; | ||
2473 | goto retry; | ||
2474 | } | ||
2464 | if (nval != uval) | 2475 | if (nval != uval) |
2465 | goto retry; | 2476 | goto retry; |
2466 | 2477 | ||