kernel/futex/core.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/kernel/futex/core.c b/kernel/futex/core.c index 326bfe6549d7..9e1bd76652d8 100644 --- a/kernel/futex/core.c +++ b/kernel/futex/core.c @@ -464,13 +464,32 @@ int futex_cmpxchg_value_locked(u32 *curval, u32 __user *uaddr, u32 uval, u32 new int futex_get_value_locked(u32 *dest, u32 __user *from) { - int ret; + u32 val; pagefault_disable(); - ret = __get_user(*dest, from); + /* + * The user address has been verified by get_futex_key(), + * and futex_cmpxchg_value_locked() trusts that, but we do + * not have any other ways to do it well, so we do the + * full user access song and dance here. + */ + if (can_do_masked_user_access()) + from = masked_user_access_begin(from); + else if (!user_read_access_begin(from, sizeof(*from))) + goto enable_and_error; + + unsafe_get_user(val, from, Efault); + user_access_end(); pagefault_enable(); - return ret ? -EFAULT : 0; + *dest = val; + return 0; + +Efault: + user_access_end(); +enable_and_error: + pagefault_enable(); + return -EFAULT; } /**