Skip to content

Commit 81429eb

Browse files
committed
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
2 parents be5fa3a + e50be64 commit 81429eb

File tree

7 files changed

+27
-31
lines changed

7 files changed

+27
-31
lines changed

arch/arm64/include/asm/asm-uaccess.h

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -58,23 +58,6 @@ alternative_else_nop_endif
5858
.endm
5959
#endif
6060

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-
7861
/*
7962
* Remove the address tag from a virtual address, if present.
8063
*/

arch/arm64/include/asm/uaccess.h

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -378,20 +378,34 @@ do { \
378378
extern unsigned long __must_check __arch_copy_from_user(void *to, const void __user *from, unsigned long n);
379379
#define raw_copy_from_user(to, from, n) \
380380
({ \
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; \
382387
})
383388

384389
extern unsigned long __must_check __arch_copy_to_user(void __user *to, const void *from, unsigned long n);
385390
#define raw_copy_to_user(to, from, n) \
386391
({ \
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; \
388398
})
389399

390400
extern unsigned long __must_check __arch_copy_in_user(void __user *to, const void __user *from, unsigned long n);
391401
#define raw_copy_in_user(to, from, n) \
392402
({ \
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; \
395409
})
396410

397411
#define INLINE_COPY_TO_USER
@@ -400,8 +414,11 @@ extern unsigned long __must_check __arch_copy_in_user(void __user *to, const voi
400414
extern unsigned long __must_check __arch_clear_user(void __user *to, unsigned long n);
401415
static inline unsigned long __must_check __clear_user(void __user *to, unsigned long n)
402416
{
403-
if (access_ok(to, n))
417+
if (access_ok(to, n)) {
418+
uaccess_enable_not_uao();
404419
n = __arch_clear_user(__uaccess_mask_ptr(to), n);
420+
uaccess_disable_not_uao();
421+
}
405422
return n;
406423
}
407424
#define clear_user __clear_user

arch/arm64/lib/clear_user.S

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
* Alignment fixed up by hardware.
2121
*/
2222
ENTRY(__arch_clear_user)
23-
uaccess_enable_not_uao x2, x3, x4
2423
mov x2, x1 // save the size for fixup return
2524
subs x1, x1, #8
2625
b.mi 2f
@@ -40,7 +39,6 @@ uao_user_alternative 9f, strh, sttrh, wzr, x0, 2
4039
b.mi 5f
4140
uao_user_alternative 9f, strb, sttrb, wzr, x0, 0
4241
5: mov x0, #0
43-
uaccess_disable_not_uao x2, x3
4442
ret
4543
ENDPROC(__arch_clear_user)
4644
EXPORT_SYMBOL(__arch_clear_user)

arch/arm64/lib/copy_from_user.S

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,8 @@
5454

5555
end .req x5
5656
ENTRY(__arch_copy_from_user)
57-
uaccess_enable_not_uao x3, x4, x5
5857
add end, x0, x2
5958
#include "copy_template.S"
60-
uaccess_disable_not_uao x3, x4
6159
mov x0, #0 // Nothing to copy
6260
ret
6361
ENDPROC(__arch_copy_from_user)

arch/arm64/lib/copy_in_user.S

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,8 @@
5656
end .req x5
5757

5858
ENTRY(__arch_copy_in_user)
59-
uaccess_enable_not_uao x3, x4, x5
6059
add end, x0, x2
6160
#include "copy_template.S"
62-
uaccess_disable_not_uao x3, x4
6361
mov x0, #0
6462
ret
6563
ENDPROC(__arch_copy_in_user)

arch/arm64/lib/copy_to_user.S

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,8 @@
5353

5454
end .req x5
5555
ENTRY(__arch_copy_to_user)
56-
uaccess_enable_not_uao x3, x4, x5
5756
add end, x0, x2
5857
#include "copy_template.S"
59-
uaccess_disable_not_uao x3, x4
6058
mov x0, #0
6159
ret
6260
ENDPROC(__arch_copy_to_user)

arch/arm64/lib/uaccess_flushcache.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@ void memcpy_page_flushcache(char *to, struct page *page, size_t offset,
2828
unsigned long __copy_user_flushcache(void *to, const void __user *from,
2929
unsigned long n)
3030
{
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();
3236

3337
/* See above */
3438
__clean_dcache_area_pop(to, n - rc);

0 commit comments

Comments
 (0)