diff --git a/sys/arm64/arm64/copyinout.S b/sys/arm64/arm64/copyinout.S --- a/sys/arm64/arm64/copyinout.S +++ b/sys/arm64/arm64/copyinout.S @@ -32,12 +32,18 @@ #include #include +#include #include #include "assym.inc" .macro check_user_access user_arg, size_arg, bad_access_func - adds x6, x\user_arg, x\size_arg + /* + * Clear the top byte of the userspace address before checking against + * VM_MAXUSER_ADDRESS + */ + and x6, x\user_arg, #(TBI_ADDR_MASK) + adds x6, x6, x\size_arg b.cs \bad_access_func ldr x7, =VM_MAXUSER_ADDRESS cmp x6, x7 @@ -100,11 +106,17 @@ adr x6, copyio_fault /* Get the handler address */ SET_FAULT_HANDLER(x6, x7) /* Set the handler */ + /* + * Clear the top byte of the userspace address before checking against + * VM_MAXUSER_ADDRESS + */ + and x6, x0, #(TBI_ADDR_MASK) ldr x7, =VM_MAXUSER_ADDRESS -1: cmp x0, x7 +1: cmp x6, x7 b.cs copyio_fault ldtrb w4, [x0] /* Load from uaddr */ add x0, x0, #1 /* Next char */ + add x6, x6, #1 /* Increment masked address */ strb w4, [x1], #1 /* Store in kaddr */ add x5, x5, #1 /* count++ */ cbz w4, 2f /* Break when NUL-terminated */ diff --git a/sys/arm64/arm64/locore.S b/sys/arm64/arm64/locore.S --- a/sys/arm64/arm64/locore.S +++ b/sys/arm64/arm64/locore.S @@ -945,6 +945,9 @@ /* Set TCR.AS with x3 */ bfi x2, x3, #(TCR_ASID_SHIFT), #(TCR_ASID_WIDTH) + /* Enable Top Byte Ignore (TBI) */ + orr x2, x2, #(TCR_TBI0) + /* * Check if the HW supports access flag updates, and set * TCR_EL1.HA accordingly. The TCR_EL1.HD flag to enable diff --git a/sys/arm64/arm64/support.S b/sys/arm64/arm64/support.S --- a/sys/arm64/arm64/support.S +++ b/sys/arm64/arm64/support.S @@ -39,8 +39,13 @@ #include "assym.inc" .macro check_user_access user_arg, limit, bad_addr_func + /* + * TBI is enabled by default, so clear the top byte of the userspace address + * before checking whether it's within the given limit + */ + and x6, x\user_arg, #(TBI_ADDR_MASK) ldr x7, =(\limit) - cmp x\user_arg, x7 + cmp x6, x7 b.cs \bad_addr_func .endm diff --git a/sys/arm64/include/armreg.h b/sys/arm64/include/armreg.h --- a/sys/arm64/include/armreg.h +++ b/sys/arm64/include/armreg.h @@ -2757,6 +2757,7 @@ #define REVIDR_EL1_op2 6 /* TCR_EL1 - Translation Control Register */ +#define TCR_EL1 MRS_REG(TCR_EL1) #define TCR_EL1_REG MRS_REG_ALT_NAME(TCR_EL1) #define TCR_EL1_op0 3 #define TCR_EL1_op1 0 diff --git a/sys/arm64/include/vmparam.h b/sys/arm64/include/vmparam.h --- a/sys/arm64/include/vmparam.h +++ b/sys/arm64/include/vmparam.h @@ -211,6 +211,8 @@ /* The address bits that hold a pointer authentication code */ #define PAC_ADDR_MASK (0xff7f000000000000UL) +#define TBI_ADDR_MASK (0x00FFFFFFFFFFFFFFUL) + /* If true addr is in the kernel address space */ #define ADDR_IS_KERNEL(addr) (((addr) & (1ul << 55)) == (1ul << 55)) /* If true addr is in its canonical form (i.e. no TBI, PAC, etc.) */