Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux

Pull arm64 fix from Will Deacon:
"Ensure PAN is re-enabled following user fault in uaccess routines.

After I thought we were done for 5.4, we had a report this week of a
nasty issue that has been shown to leak data between different user
address spaces thanks to corruption of entries in the TLB. In
hindsight, we should have spotted this in review when the PAN code was
merged back in v4.3, but hindsight is 20/20 and I'm trying not to beat
myself up too much about it despite being fairly miserable.

Anyway, the fix is "obvious" but the actual failure is more more
subtle, and is described in the commit message. I've included a fairly
mechanical follow-up patch here as well, which moves this checking out
into the C wrappers which is what we do for {get,put}_user() already
and allows us to remove these bloody assembly macros entirely. The
patches have passed kernelci [1] [2] [3] and CKI [4] tests over night,
as well as some targetted testing [5] for this particular issue.

The first patch is tagged for stable and should be applied to 4.14,
4.19 and 5.3. I have separate backports for 4.4 and 4.9, which I'll
send out once this has landed in your tree (although the original
patch applies cleanly, it won't build for those two trees).

Thanks to Pavel Tatashin for reporting this and Mark Rutland for
helping to diagnose the issue and review/test the solution"

* tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux:
arm64: uaccess: Remove uaccess_*_not_uao asm macros
arm64: uaccess: Ensure PAN is re-enabled after unhandled uaccess fault

+27 -31
-17
arch/arm64/include/asm/asm-uaccess.h
··· 59 59 #endif 60 60 61 61 /* 62 - * These macros are no-ops when UAO is present. 63 - */ 64 - .macro uaccess_disable_not_uao, tmp1, tmp2 65 - uaccess_ttbr0_disable \tmp1, \tmp2 66 - alternative_if ARM64_ALT_PAN_NOT_UAO 67 - SET_PSTATE_PAN(1) 68 - alternative_else_nop_endif 69 - .endm 70 - 71 - .macro uaccess_enable_not_uao, tmp1, tmp2, tmp3 72 - uaccess_ttbr0_enable \tmp1, \tmp2, \tmp3 73 - alternative_if ARM64_ALT_PAN_NOT_UAO 74 - SET_PSTATE_PAN(0) 75 - alternative_else_nop_endif 76 - .endm 77 - 78 - /* 79 62 * Remove the address tag from a virtual address, if present. 80 63 */ 81 64 .macro untagged_addr, dst, addr
+22 -5
arch/arm64/include/asm/uaccess.h
··· 378 378 extern unsigned long __must_check __arch_copy_from_user(void *to, const void __user *from, unsigned long n); 379 379 #define raw_copy_from_user(to, from, n) \ 380 380 ({ \ 381 - __arch_copy_from_user((to), __uaccess_mask_ptr(from), (n)); \ 381 + unsigned long __acfu_ret; \ 382 + uaccess_enable_not_uao(); \ 383 + __acfu_ret = __arch_copy_from_user((to), \ 384 + __uaccess_mask_ptr(from), (n)); \ 385 + uaccess_disable_not_uao(); \ 386 + __acfu_ret; \ 382 387 }) 383 388 384 389 extern unsigned long __must_check __arch_copy_to_user(void __user *to, const void *from, unsigned long n); 385 390 #define raw_copy_to_user(to, from, n) \ 386 391 ({ \ 387 - __arch_copy_to_user(__uaccess_mask_ptr(to), (from), (n)); \ 392 + unsigned long __actu_ret; \ 393 + uaccess_enable_not_uao(); \ 394 + __actu_ret = __arch_copy_to_user(__uaccess_mask_ptr(to), \ 395 + (from), (n)); \ 396 + uaccess_disable_not_uao(); \ 397 + __actu_ret; \ 388 398 }) 389 399 390 400 extern unsigned long __must_check __arch_copy_in_user(void __user *to, const void __user *from, unsigned long n); 391 401 #define raw_copy_in_user(to, from, n) \ 392 402 ({ \ 393 - __arch_copy_in_user(__uaccess_mask_ptr(to), \ 394 - __uaccess_mask_ptr(from), (n)); \ 403 + unsigned long __aciu_ret; \ 404 + uaccess_enable_not_uao(); \ 405 + __aciu_ret = __arch_copy_in_user(__uaccess_mask_ptr(to), \ 406 + __uaccess_mask_ptr(from), (n)); \ 407 + uaccess_disable_not_uao(); \ 408 + __aciu_ret; \ 395 409 }) 396 410 397 411 #define INLINE_COPY_TO_USER ··· 414 400 extern unsigned long __must_check __arch_clear_user(void __user *to, unsigned long n); 415 401 static inline unsigned long __must_check __clear_user(void __user *to, unsigned long n) 416 402 { 417 - if (access_ok(to, n)) 403 + if (access_ok(to, n)) { 404 + uaccess_enable_not_uao(); 418 405 n = __arch_clear_user(__uaccess_mask_ptr(to), n); 406 + uaccess_disable_not_uao(); 407 + } 419 408 return n; 420 409 } 421 410 #define clear_user __clear_user
-2
arch/arm64/lib/clear_user.S
··· 20 20 * Alignment fixed up by hardware. 21 21 */ 22 22 ENTRY(__arch_clear_user) 23 - uaccess_enable_not_uao x2, x3, x4 24 23 mov x2, x1 // save the size for fixup return 25 24 subs x1, x1, #8 26 25 b.mi 2f ··· 39 40 b.mi 5f 40 41 uao_user_alternative 9f, strb, sttrb, wzr, x0, 0 41 42 5: mov x0, #0 42 - uaccess_disable_not_uao x2, x3 43 43 ret 44 44 ENDPROC(__arch_clear_user) 45 45 EXPORT_SYMBOL(__arch_clear_user)
-2
arch/arm64/lib/copy_from_user.S
··· 54 54 55 55 end .req x5 56 56 ENTRY(__arch_copy_from_user) 57 - uaccess_enable_not_uao x3, x4, x5 58 57 add end, x0, x2 59 58 #include "copy_template.S" 60 - uaccess_disable_not_uao x3, x4 61 59 mov x0, #0 // Nothing to copy 62 60 ret 63 61 ENDPROC(__arch_copy_from_user)
-2
arch/arm64/lib/copy_in_user.S
··· 56 56 end .req x5 57 57 58 58 ENTRY(__arch_copy_in_user) 59 - uaccess_enable_not_uao x3, x4, x5 60 59 add end, x0, x2 61 60 #include "copy_template.S" 62 - uaccess_disable_not_uao x3, x4 63 61 mov x0, #0 64 62 ret 65 63 ENDPROC(__arch_copy_in_user)
-2
arch/arm64/lib/copy_to_user.S
··· 53 53 54 54 end .req x5 55 55 ENTRY(__arch_copy_to_user) 56 - uaccess_enable_not_uao x3, x4, x5 57 56 add end, x0, x2 58 57 #include "copy_template.S" 59 - uaccess_disable_not_uao x3, x4 60 58 mov x0, #0 61 59 ret 62 60 ENDPROC(__arch_copy_to_user)
+5 -1
arch/arm64/lib/uaccess_flushcache.c
··· 28 28 unsigned long __copy_user_flushcache(void *to, const void __user *from, 29 29 unsigned long n) 30 30 { 31 - unsigned long rc = __arch_copy_from_user(to, from, n); 31 + unsigned long rc; 32 + 33 + uaccess_enable_not_uao(); 34 + rc = __arch_copy_from_user(to, from, n); 35 + uaccess_disable_not_uao(); 32 36 33 37 /* See above */ 34 38 __clean_dcache_area_pop(to, n - rc);