Christophe Leroy's on March 27, 2020 5:21 pm:
> 
> 
> Le 27/03/2020 à 08:02, Nicholas Piggin a écrit :
>> get/put_user can be called with nontrivial arguments. fs/proc/page.c
>> has a good example:
>> 
>>      if (put_user(stable_page_flags(ppage), out)) {
>> 
>> stable_page_flags is quite a lot of code, including spin locks in the
>> page allocator.
>> 
>> Ensure these arguments are evaluated before user access is allowed.
>> This improves security by reducing code with access to userspace, but
>> it also fixes a PREEMPT bug with KUAP on powerpc/64s:
>> stable_page_flags is currently called with AMR set to allow writes,
>> it ends up calling spin_unlock(), which can call preempt_schedule. But
>> the task switch code can not be called with AMR set (it relies on
>> interrupts saving the register), so this blows up.
>> 
>> It's fine if the code inside allow_user_access is preemptible, because
>> a timer or IPI will save the AMR, but it's not okay to explicitly
>> cause a reschedule.
>> 
>> Signed-off-by: Nicholas Piggin <npig...@gmail.com>
>> ---
>>   arch/powerpc/include/asm/uaccess.h | 97 ++++++++++++++++++------------
>>   1 file changed, 59 insertions(+), 38 deletions(-)
>> 
>> diff --git a/arch/powerpc/include/asm/uaccess.h 
>> b/arch/powerpc/include/asm/uaccess.h
>> index 670910df3cc7..1cf8595aeef1 100644
>> --- a/arch/powerpc/include/asm/uaccess.h
>> +++ b/arch/powerpc/include/asm/uaccess.h
>> @@ -162,36 +162,48 @@ do {                                                   
>>         \
>>      prevent_write_to_user(ptr, size);                       \
>>   } while (0)
>>   
>> -#define __put_user_nocheck(x, ptr, size, do_allow)                  \
>> +#define __put_user_nocheck(x, ptr, size, do_allow)          \
> 
> No need to touch this line. Anyway at the end, you still have several \ 
> which are not aligned.
> 
>>   ({                                                         \
>>      long __pu_err;                                          \
>>      __typeof__(*(ptr)) __user *__pu_addr = (ptr);           \
>> +    __typeof__(*(ptr)) __pu_val = (x);                      \
>> +    __typeof__(size) __pu_size = (size);                    \
>> +                                                            \
>>      if (!is_kernel_addr((unsigned long)__pu_addr))          \
>>              might_fault();                                  \
>> -    __chk_user_ptr(ptr);                                    \
>> -    if (do_allow)                                                           
>> \
> 
> No need to touch that line
> 
>> -            __put_user_size((x), __pu_addr, (size), __pu_err);              
>> \
>> -    else                                                                    
>> \
> 
> No need to touch that line

Okay fair point I can redo the patch.

Thanks,
Nick

Reply via email to