Skip to content

Commit 597399d

Browse files
committed
arm64: tags: Preserve tags for addresses translated via TTBR1
Sign-extending TTBR1 addresses when converting to an untagged address breaks the documented POSIX semantics for mlock() in some obscure error cases where we end up returning -EINVAL instead of -ENOMEM as a direct result of rewriting the upper address bits. Rework the untagged_addr() macro to preserve the upper address bits for TTBR1 addresses and only clear the tag bits for user addresses. This matches the behaviour of the 'clear_address_tag' assembly macro, so rename that and align the implementations at the same time so that they use the same instruction sequences for the tag manipulation. Link: https://lore.kernel.org/stable/[email protected]/ Reported-by: Jan Stancek <[email protected]> Tested-by: Jan Stancek <[email protected]> Reviewed-by: Catalin Marinas <[email protected]> Tested-by: Catalin Marinas <[email protected]> Reviewed-by: Vincenzo Frascino <[email protected]> Tested-by: Vincenzo Frascino <[email protected]> Reviewed-by: Andrey Konovalov <[email protected]> Signed-off-by: Will Deacon <[email protected]>
1 parent 3813733 commit 597399d

File tree

3 files changed

+13
-8
lines changed

3 files changed

+13
-8
lines changed

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,9 @@ alternative_else_nop_endif
7878
/*
7979
* Remove the address tag from a virtual address, if present.
8080
*/
81-
.macro clear_address_tag, dst, addr
82-
tst \addr, #(1 << 55)
83-
bic \dst, \addr, #(0xff << 56)
84-
csel \dst, \dst, \addr, eq
81+
.macro untagged_addr, dst, addr
82+
sbfx \dst, \addr, #0, #56
83+
and \dst, \dst, \addr
8584
.endm
8685

8786
#endif

arch/arm64/include/asm/memory.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,12 +215,18 @@ static inline unsigned long kaslr_offset(void)
215215
* up with a tagged userland pointer. Clear the tag to get a sane pointer to
216216
* pass on to access_ok(), for instance.
217217
*/
218-
#define untagged_addr(addr) \
218+
#define __untagged_addr(addr) \
219219
((__force __typeof__(addr))sign_extend64((__force u64)(addr), 55))
220220

221+
#define untagged_addr(addr) ({ \
222+
u64 __addr = (__force u64)addr; \
223+
__addr &= __untagged_addr(__addr); \
224+
(__force __typeof__(addr))__addr; \
225+
})
226+
221227
#ifdef CONFIG_KASAN_SW_TAGS
222228
#define __tag_shifted(tag) ((u64)(tag) << 56)
223-
#define __tag_reset(addr) untagged_addr(addr)
229+
#define __tag_reset(addr) __untagged_addr(addr)
224230
#define __tag_get(addr) (__u8)((u64)(addr) >> 56)
225231
#else
226232
#define __tag_shifted(tag) 0UL

arch/arm64/kernel/entry.S

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,7 @@ el1_da:
604604
*/
605605
mrs x3, far_el1
606606
inherit_daif pstate=x23, tmp=x2
607-
clear_address_tag x0, x3
607+
untagged_addr x0, x3
608608
mov x2, sp // struct pt_regs
609609
bl do_mem_abort
610610

@@ -808,7 +808,7 @@ el0_da:
808808
mrs x26, far_el1
809809
ct_user_exit_irqoff
810810
enable_daif
811-
clear_address_tag x0, x26
811+
untagged_addr x0, x26
812812
mov x1, x25
813813
mov x2, sp
814814
bl do_mem_abort

0 commit comments

Comments
 (0)