Skip to content

Commit 80e4e56

Browse files
committed
Merge branch 'for-next/bti-user' into for-next/bti
Merge in user support for Branch Target Identification, which narrowly missed the cut for 5.7 after a late ABI concern. * for-next/bti-user: arm64: bti: Document behaviour for dynamically linked binaries arm64: elf: Fix allnoconfig kernel build with !ARCH_USE_GNU_PROPERTY arm64: BTI: Add Kconfig entry for userspace BTI mm: smaps: Report arm64 guarded pages in smaps arm64: mm: Display guarded pages in ptdump KVM: arm64: BTI: Reset BTYPE when skipping emulated instructions arm64: BTI: Reset BTYPE when skipping emulated instructions arm64: traps: Shuffle code to eliminate forward declarations arm64: unify native/compat instruction skipping arm64: BTI: Decode BYTPE bits when printing PSTATE arm64: elf: Enable BTI at exec based on ELF program properties elf: Allow arch to tweak initial mmap prot flags arm64: Basic Branch Target Identification support ELF: Add ELF program property parsing support ELF: UAPI and Kconfig additions for ELF program properties
2 parents 6a8b55e + 5d1b631 commit 80e4e56

35 files changed

+564
-74
lines changed

Documentation/arm64/cpu-feature-registers.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,8 @@ infrastructure:
176176
+------------------------------+---------+---------+
177177
| SSBS | [7-4] | y |
178178
+------------------------------+---------+---------+
179+
| BT | [3-0] | y |
180+
+------------------------------+---------+---------+
179181

180182

181183
4) MIDR_EL1 - Main ID Register

Documentation/arm64/elf_hwcaps.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,11 @@ HWCAP2_RNG
236236

237237
Functionality implied by ID_AA64ISAR0_EL1.RNDR == 0b0001.
238238

239+
HWCAP2_BTI
240+
241+
Functionality implied by ID_AA64PFR0_EL1.BT == 0b0001.
242+
243+
239244
4. Unused AT_HWCAP bits
240245
-----------------------
241246

Documentation/filesystems/proc.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,7 @@ encoded manner. The codes are the following:
543543
hg huge page advise flag
544544
nh no huge page advise flag
545545
mg mergable advise flag
546+
bt - arm64 BTI guarded page
546547
== =======================================
547548

548549
Note that there is no guarantee that every flag and associated mnemonic will

arch/arm64/Kconfig

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ config ARM64
99
select ACPI_MCFG if (ACPI && PCI)
1010
select ACPI_SPCR_TABLE if ACPI
1111
select ACPI_PPTT if ACPI
12+
select ARCH_BINFMT_ELF_STATE
1213
select ARCH_HAS_DEBUG_VIRTUAL
1314
select ARCH_HAS_DEVMEM_IS_ALLOWED
1415
select ARCH_HAS_DMA_PREP_COHERENT
@@ -32,6 +33,7 @@ config ARM64
3233
select ARCH_HAS_SYSCALL_WRAPPER
3334
select ARCH_HAS_TEARDOWN_DMA_OPS if IOMMU_SUPPORT
3435
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
36+
select ARCH_HAVE_ELF_PROT
3537
select ARCH_HAVE_NMI_SAFE_CMPXCHG
3638
select ARCH_INLINE_READ_LOCK if !PREEMPTION
3739
select ARCH_INLINE_READ_LOCK_BH if !PREEMPTION
@@ -61,6 +63,7 @@ config ARM64
6163
select ARCH_INLINE_SPIN_UNLOCK_IRQRESTORE if !PREEMPTION
6264
select ARCH_KEEP_MEMBLOCK
6365
select ARCH_USE_CMPXCHG_LOCKREF
66+
select ARCH_USE_GNU_PROPERTY
6467
select ARCH_USE_QUEUED_RWLOCKS
6568
select ARCH_USE_QUEUED_SPINLOCKS
6669
select ARCH_SUPPORTS_MEMORY_FAILURE
@@ -1584,6 +1587,28 @@ endmenu
15841587

15851588
menu "ARMv8.5 architectural features"
15861589

1590+
config ARM64_BTI
1591+
bool "Branch Target Identification support"
1592+
default y
1593+
help
1594+
Branch Target Identification (part of the ARMv8.5 Extensions)
1595+
provides a mechanism to limit the set of locations to which computed
1596+
branch instructions such as BR or BLR can jump.
1597+
1598+
To make use of BTI on CPUs that support it, say Y.
1599+
1600+
BTI is intended to provide complementary protection to other control
1601+
flow integrity protection mechanisms, such as the Pointer
1602+
authentication mechanism provided as part of the ARMv8.3 Extensions.
1603+
For this reason, it does not make sense to enable this option without
1604+
also enabling support for pointer authentication. Thus, when
1605+
enabling this option you should also select ARM64_PTR_AUTH=y.
1606+
1607+
Userspace binaries must also be specifically compiled to make use of
1608+
this mechanism. If you say N here or the hardware does not support
1609+
BTI, such binaries can still run, but you get no additional
1610+
enforcement of branch destinations.
1611+
15871612
config ARM64_E0PD
15881613
bool "Enable support for E0PD"
15891614
default y

arch/arm64/include/asm/cpucaps.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@
6161
#define ARM64_HAS_AMU_EXTN 51
6262
#define ARM64_HAS_ADDRESS_AUTH 52
6363
#define ARM64_HAS_GENERIC_AUTH 53
64+
#define ARM64_BTI 54
6465

65-
#define ARM64_NCAPS 54
66+
#define ARM64_NCAPS 55
6667

6768
#endif /* __ASM_CPUCAPS_H */

arch/arm64/include/asm/cpufeature.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,11 @@ static inline bool system_has_prio_mask_debugging(void)
680680
system_uses_irq_prio_masking();
681681
}
682682

683+
static inline bool system_supports_bti(void)
684+
{
685+
return IS_ENABLED(CONFIG_ARM64_BTI) && cpus_have_const_cap(ARM64_BTI);
686+
}
687+
683688
#define ARM64_BP_HARDEN_UNKNOWN -1
684689
#define ARM64_BP_HARDEN_WA_NEEDED 0
685690
#define ARM64_BP_HARDEN_NOT_REQUIRED 1

arch/arm64/include/asm/elf.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,11 @@
114114

115115
#ifndef __ASSEMBLY__
116116

117+
#include <uapi/linux/elf.h>
117118
#include <linux/bug.h>
119+
#include <linux/errno.h>
120+
#include <linux/fs.h>
121+
#include <linux/types.h>
118122
#include <asm/processor.h> /* for signal_minsigstksz, used by ARCH_DLINFO */
119123

120124
typedef unsigned long elf_greg_t;
@@ -224,6 +228,52 @@ extern int aarch32_setup_additional_pages(struct linux_binprm *bprm,
224228

225229
#endif /* CONFIG_COMPAT */
226230

231+
struct arch_elf_state {
232+
int flags;
233+
};
234+
235+
#define ARM64_ELF_BTI (1 << 0)
236+
237+
#define INIT_ARCH_ELF_STATE { \
238+
.flags = 0, \
239+
}
240+
241+
static inline int arch_parse_elf_property(u32 type, const void *data,
242+
size_t datasz, bool compat,
243+
struct arch_elf_state *arch)
244+
{
245+
/* No known properties for AArch32 yet */
246+
if (IS_ENABLED(CONFIG_COMPAT) && compat)
247+
return 0;
248+
249+
if (type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) {
250+
const u32 *p = data;
251+
252+
if (datasz != sizeof(*p))
253+
return -ENOEXEC;
254+
255+
if (system_supports_bti() &&
256+
(*p & GNU_PROPERTY_AARCH64_FEATURE_1_BTI))
257+
arch->flags |= ARM64_ELF_BTI;
258+
}
259+
260+
return 0;
261+
}
262+
263+
static inline int arch_elf_pt_proc(void *ehdr, void *phdr,
264+
struct file *f, bool is_interp,
265+
struct arch_elf_state *state)
266+
{
267+
return 0;
268+
}
269+
270+
static inline int arch_check_elf(void *ehdr, bool has_interp,
271+
void *interp_ehdr,
272+
struct arch_elf_state *state)
273+
{
274+
return 0;
275+
}
276+
227277
#endif /* !__ASSEMBLY__ */
228278

229279
#endif

arch/arm64/include/asm/esr.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
#define ESR_ELx_EC_PAC (0x09) /* EL2 and above */
2323
/* Unallocated EC: 0x0A - 0x0B */
2424
#define ESR_ELx_EC_CP14_64 (0x0C)
25-
/* Unallocated EC: 0x0d */
25+
#define ESR_ELx_EC_BTI (0x0D)
2626
#define ESR_ELx_EC_ILL (0x0E)
2727
/* Unallocated EC: 0x0F - 0x10 */
2828
#define ESR_ELx_EC_SVC32 (0x11)

arch/arm64/include/asm/exception.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ static inline u32 disr_to_esr(u64 disr)
3434
asmlinkage void enter_from_user_mode(void);
3535
void do_mem_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs);
3636
void do_undefinstr(struct pt_regs *regs);
37+
void do_bti(struct pt_regs *regs);
3738
asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr);
3839
void do_debug_exception(unsigned long addr_if_watchpoint, unsigned int esr,
3940
struct pt_regs *regs);

arch/arm64/include/asm/hwcap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
#define KERNEL_HWCAP_BF16 __khwcap2_feature(BF16)
9595
#define KERNEL_HWCAP_DGH __khwcap2_feature(DGH)
9696
#define KERNEL_HWCAP_RNG __khwcap2_feature(RNG)
97+
#define KERNEL_HWCAP_BTI __khwcap2_feature(BTI)
9798

9899
/*
99100
* This yields a mask that user programs can use to figure out what

arch/arm64/include/asm/kvm_emulate.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -507,10 +507,12 @@ static inline unsigned long vcpu_data_host_to_guest(struct kvm_vcpu *vcpu,
507507

508508
static __always_inline void kvm_skip_instr(struct kvm_vcpu *vcpu, bool is_wide_instr)
509509
{
510-
if (vcpu_mode_is_32bit(vcpu))
510+
if (vcpu_mode_is_32bit(vcpu)) {
511511
kvm_skip_instr32(vcpu, is_wide_instr);
512-
else
512+
} else {
513513
*vcpu_pc(vcpu) += 4;
514+
*vcpu_cpsr(vcpu) &= ~PSR_BTYPE_MASK;
515+
}
514516

515517
/* advance the singlestep state machine */
516518
*vcpu_cpsr(vcpu) &= ~DBG_SPSR_SS;

arch/arm64/include/asm/mman.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
#ifndef __ASM_MMAN_H__
3+
#define __ASM_MMAN_H__
4+
5+
#include <linux/compiler.h>
6+
#include <linux/types.h>
7+
#include <uapi/asm/mman.h>
8+
9+
static inline unsigned long arch_calc_vm_prot_bits(unsigned long prot,
10+
unsigned long pkey __always_unused)
11+
{
12+
if (system_supports_bti() && (prot & PROT_BTI))
13+
return VM_ARM64_BTI;
14+
15+
return 0;
16+
}
17+
#define arch_calc_vm_prot_bits(prot, pkey) arch_calc_vm_prot_bits(prot, pkey)
18+
19+
static inline pgprot_t arch_vm_get_page_prot(unsigned long vm_flags)
20+
{
21+
return (vm_flags & VM_ARM64_BTI) ? __pgprot(PTE_GP) : __pgprot(0);
22+
}
23+
#define arch_vm_get_page_prot(vm_flags) arch_vm_get_page_prot(vm_flags)
24+
25+
static inline bool arch_validate_prot(unsigned long prot,
26+
unsigned long addr __always_unused)
27+
{
28+
unsigned long supported = PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM;
29+
30+
if (system_supports_bti())
31+
supported |= PROT_BTI;
32+
33+
return (prot & ~supported) == 0;
34+
}
35+
#define arch_validate_prot(prot, addr) arch_validate_prot(prot, addr)
36+
37+
#endif /* ! __ASM_MMAN_H__ */

arch/arm64/include/asm/pgtable-hwdef.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@
151151
#define PTE_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */
152152
#define PTE_AF (_AT(pteval_t, 1) << 10) /* Access Flag */
153153
#define PTE_NG (_AT(pteval_t, 1) << 11) /* nG */
154+
#define PTE_GP (_AT(pteval_t, 1) << 50) /* BTI guarded */
154155
#define PTE_DBM (_AT(pteval_t, 1) << 51) /* Dirty Bit Management */
155156
#define PTE_CONT (_AT(pteval_t, 1) << 52) /* Contiguous range */
156157
#define PTE_PXN (_AT(pteval_t, 1) << 53) /* Privileged XN */

arch/arm64/include/asm/pgtable.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -660,7 +660,7 @@ static inline phys_addr_t pgd_page_paddr(pgd_t pgd)
660660
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
661661
{
662662
const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY |
663-
PTE_PROT_NONE | PTE_VALID | PTE_WRITE;
663+
PTE_PROT_NONE | PTE_VALID | PTE_WRITE | PTE_GP;
664664
/* preserve the hardware dirty information */
665665
if (pte_hw_dirty(pte))
666666
pte = pte_mkdirty(pte);

arch/arm64/include/asm/ptrace.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#define GIC_PRIO_PSR_I_SET (1 << 4)
3636

3737
/* Additional SPSR bits not exposed in the UABI */
38+
3839
#define PSR_IL_BIT (1 << 20)
3940

4041
/* AArch32-specific ptrace requests */

arch/arm64/include/asm/sysreg.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,8 @@
552552
#endif
553553

554554
/* SCTLR_EL1 specific flags. */
555+
#define SCTLR_EL1_BT1 (BIT(36))
556+
#define SCTLR_EL1_BT0 (BIT(35))
555557
#define SCTLR_EL1_UCI (BIT(26))
556558
#define SCTLR_EL1_E0E (BIT(24))
557559
#define SCTLR_EL1_SPAN (BIT(23))
@@ -660,10 +662,12 @@
660662

661663
/* id_aa64pfr1 */
662664
#define ID_AA64PFR1_SSBS_SHIFT 4
665+
#define ID_AA64PFR1_BT_SHIFT 0
663666

664667
#define ID_AA64PFR1_SSBS_PSTATE_NI 0
665668
#define ID_AA64PFR1_SSBS_PSTATE_ONLY 1
666669
#define ID_AA64PFR1_SSBS_PSTATE_INSNS 2
670+
#define ID_AA64PFR1_BT_BTI 0x1
667671

668672
/* id_aa64zfr0 */
669673
#define ID_AA64ZFR0_F64MM_SHIFT 56

arch/arm64/include/uapi/asm/hwcap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,5 +73,6 @@
7373
#define HWCAP2_BF16 (1 << 14)
7474
#define HWCAP2_DGH (1 << 15)
7575
#define HWCAP2_RNG (1 << 16)
76+
#define HWCAP2_BTI (1 << 17)
7677

7778
#endif /* _UAPI__ASM_HWCAP_H */

arch/arm64/include/uapi/asm/mman.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2+
#ifndef _UAPI__ASM_MMAN_H
3+
#define _UAPI__ASM_MMAN_H
4+
5+
#include <asm-generic/mman.h>
6+
7+
#define PROT_BTI 0x10 /* BTI guarded page */
8+
9+
#endif /* ! _UAPI__ASM_MMAN_H */

arch/arm64/include/uapi/asm/ptrace.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#define PSR_I_BIT 0x00000080
4747
#define PSR_A_BIT 0x00000100
4848
#define PSR_D_BIT 0x00000200
49+
#define PSR_BTYPE_MASK 0x00000c00
4950
#define PSR_SSBS_BIT 0x00001000
5051
#define PSR_PAN_BIT 0x00400000
5152
#define PSR_UAO_BIT 0x00800000
@@ -55,6 +56,8 @@
5556
#define PSR_Z_BIT 0x40000000
5657
#define PSR_N_BIT 0x80000000
5758

59+
#define PSR_BTYPE_SHIFT 10
60+
5861
/*
5962
* Groups of PSR bits
6063
*/
@@ -63,6 +66,12 @@
6366
#define PSR_x 0x0000ff00 /* Extension */
6467
#define PSR_c 0x000000ff /* Control */
6568

69+
/* Convenience names for the values of PSTATE.BTYPE */
70+
#define PSR_BTYPE_NONE (0b00 << PSR_BTYPE_SHIFT)
71+
#define PSR_BTYPE_JC (0b01 << PSR_BTYPE_SHIFT)
72+
#define PSR_BTYPE_C (0b10 << PSR_BTYPE_SHIFT)
73+
#define PSR_BTYPE_J (0b11 << PSR_BTYPE_SHIFT)
74+
6675
/* syscall emulation path in ptrace */
6776
#define PTRACE_SYSEMU 31
6877
#define PTRACE_SYSEMU_SINGLESTEP 32

0 commit comments

Comments
 (0)