Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2cf899dc authored by Will Deacon's avatar Will Deacon Committed by Alistair Delva
Browse files

BACKPORT: arm64: tags: Preserve tags for addresses translated via TTBR1

(Upstream commit 597399d0cb91d049fcb78fb45c7694771b583bb7).

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/20191014162651.GF19200@arrakis.emea.arm.com/


Reported-by: default avatarJan Stancek <jstancek@redhat.com>
Tested-by: default avatarJan Stancek <jstancek@redhat.com>
Reviewed-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
Tested-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
Reviewed-by: default avatarVincenzo Frascino <vincenzo.frascino@arm.com>
Tested-by: default avatarVincenzo Frascino <vincenzo.frascino@arm.com>
Reviewed-by: default avatarAndrey Konovalov <andreyknvl@google.com>
Signed-off-by: default avatarWill Deacon <will@kernel.org>
Change-Id: Iadecb8f15c12984d228c6d6261edac5abadc3f36
Signed-off-by: default avatarAndrey Konovalov <andreyknvl@google.com>
Bug: 135692346
parent 20c724f5
Loading
Loading
Loading
Loading
+3 −4
Original line number Diff line number Diff line
@@ -78,10 +78,9 @@ alternative_else_nop_endif
/*
 * Remove the address tag from a virtual address, if present.
 */
	.macro	clear_address_tag, dst, addr
	tst	\addr, #(1 << 55)
	bic	\dst, \addr, #(0xff << 56)
	csel	\dst, \dst, \addr, eq
	.macro	untagged_addr, dst, addr
	sbfx	\dst, \addr, #0, #56
	and	\dst, \dst, \addr
	.endm

#endif
+8 −2
Original line number Diff line number Diff line
@@ -216,12 +216,18 @@ static inline unsigned long kaslr_offset(void)
 * up with a tagged userland pointer. Clear the tag to get a sane pointer to
 * pass on to access_ok(), for instance.
 */
#define untagged_addr(addr)	\
#define __untagged_addr(addr)	\
	((__force __typeof__(addr))sign_extend64((__force u64)(addr), 55))

#define untagged_addr(addr)	({					\
	u64 __addr = (__force u64)addr;					\
	__addr &= __untagged_addr(__addr);				\
	(__force __typeof__(addr))__addr;				\
})

#ifdef CONFIG_KASAN_SW_TAGS
#define __tag_shifted(tag)	((u64)(tag) << 56)
#define __tag_reset(addr)	untagged_addr(addr)
#define __tag_reset(addr)	__untagged_addr(addr)
#define __tag_get(addr)		(__u8)((u64)(addr) >> 56)
#else
#define __tag_shifted(tag)	0UL
+2 −2
Original line number Diff line number Diff line
@@ -568,7 +568,7 @@ el1_da:
	 */
	mrs	x3, far_el1
	inherit_daif	pstate=x23, tmp=x2
	clear_address_tag x0, x3
	untagged_addr x0, x3
	mov	x2, sp				// struct pt_regs
	bl	do_mem_abort

@@ -731,7 +731,7 @@ el0_da:
	mrs	x26, far_el1
	enable_daif
	ct_user_exit
	clear_address_tag x0, x26
	untagged_addr x0, x26
	mov	x1, x25
	mov	x2, sp
	bl	do_mem_abort