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/20191014162651.GF19200@arrakis.emea.arm.com/ Reported-by: Jan Stancek <jstancek@redhat.com> Tested-by: Jan Stancek <jstancek@redhat.com> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> Tested-by: Catalin Marinas <catalin.marinas@arm.com> Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com> Tested-by: Vincenzo Frascino <vincenzo.frascino@arm.com> Reviewed-by: Andrey Konovalov <andreyknvl@google.com> Signed-off-by: Will Deacon <will@kernel.org>
This commit is contained in:
Родитель
3813733595
Коммит
597399d0cb
|
@ -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
|
||||
|
|
|
@ -215,12 +215,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
|
||||
|
|
|
@ -604,7 +604,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
|
||||
|
||||
|
@ -808,7 +808,7 @@ el0_da:
|
|||
mrs x26, far_el1
|
||||
ct_user_exit_irqoff
|
||||
enable_daif
|
||||
clear_address_tag x0, x26
|
||||
untagged_addr x0, x26
|
||||
mov x1, x25
|
||||
mov x2, sp
|
||||
bl do_mem_abort
|
||||
|
|
Загрузка…
Ссылка в новой задаче