Skip to content

Commit 4853f1f

Browse files
committed
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rmk/linux
Pull ARM updates from Russell King: - Updates to AMBA bus subsystem to drop .owner struct device_driver initialisations, moving that to code instead. - Add LPAE privileged-access-never support - Add support for Clang CFI - clkdev: report over-sized device or connection strings * tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rmk/linux: (36 commits) ARM: 9398/1: Fix userspace enter on LPAE with CC_OPTIMIZE_FOR_SIZE=y clkdev: report over-sized strings when creating clkdev entries ARM: 9393/1: mm: Use conditionals for CFI branches ARM: 9392/2: Support CLANG CFI ARM: 9391/2: hw_breakpoint: Handle CFI breakpoints ARM: 9390/2: lib: Annotate loop delay instructions for CFI ARM: 9389/2: mm: Define prototypes for all per-processor calls ARM: 9388/2: mm: Type-annotate all per-processor assembly routines ARM: 9387/2: mm: Rewrite cacheflush vtables in CFI safe C ARM: 9386/2: mm: Use symbol alias for cache functions ARM: 9385/2: mm: Type-annotate all cache assembly routines ARM: 9384/2: mm: Make tlbflush routines CFI safe ARM: 9382/1: ftrace: Define ftrace_stub_graph ARM: 9358/2: Implement PAN for LPAE by TTBR0 page table walks disablement ARM: 9357/2: Reduce the number of #ifdef CONFIG_CPU_SW_DOMAIN_PAN ARM: 9356/2: Move asm statements accessing TTBCR into C functions ARM: 9355/2: Add TTBCR_* definitions to pgtable-3level-hwdef.h ARM: 9379/1: coresight: tpda: drop owner assignment ARM: 9378/1: coresight: etm4x: drop owner assignment ARM: 9377/1: hwrng: nomadik: drop owner assignment ...
2 parents ea5f6ad + f698d31 commit 4853f1f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+2607
-1013
lines changed

arch/arm/Kconfig

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ config ARM
3535
select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
3636
select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT if CPU_V7
3737
select ARCH_SUPPORTS_ATOMIC_RMW
38+
select ARCH_SUPPORTS_CFI_CLANG
3839
select ARCH_SUPPORTS_HUGETLBFS if ARM_LPAE
3940
select ARCH_SUPPORTS_PER_VMA_LOCK
4041
select ARCH_USE_BUILTIN_BSWAP
@@ -1233,9 +1234,9 @@ config HIGHPTE
12331234
consumed by page tables. Setting this option will allow
12341235
user-space 2nd level page tables to reside in high memory.
12351236

1236-
config CPU_SW_DOMAIN_PAN
1237-
bool "Enable use of CPU domains to implement privileged no-access"
1238-
depends on MMU && !ARM_LPAE
1237+
config ARM_PAN
1238+
bool "Enable privileged no-access"
1239+
depends on MMU
12391240
default y
12401241
help
12411242
Increase kernel security by ensuring that normal kernel accesses
@@ -1244,10 +1245,26 @@ config CPU_SW_DOMAIN_PAN
12441245
by ensuring that magic values (such as LIST_POISON) will always
12451246
fault when dereferenced.
12461247

1248+
The implementation uses CPU domains when !CONFIG_ARM_LPAE and
1249+
disabling of TTBR0 page table walks with CONFIG_ARM_LPAE.
1250+
1251+
config CPU_SW_DOMAIN_PAN
1252+
def_bool y
1253+
depends on ARM_PAN && !ARM_LPAE
1254+
help
1255+
Enable use of CPU domains to implement privileged no-access.
1256+
12471257
CPUs with low-vector mappings use a best-efforts implementation.
12481258
Their lower 1MB needs to remain accessible for the vectors, but
12491259
the remainder of userspace will become appropriately inaccessible.
12501260

1261+
config CPU_TTBR0_PAN
1262+
def_bool y
1263+
depends on ARM_PAN && ARM_LPAE
1264+
help
1265+
Enable privileged no-access by disabling TTBR0 page table walks when
1266+
running in kernel mode.
1267+
12511268
config HW_PERF_EVENTS
12521269
def_bool y
12531270
depends on ARM_PMU

arch/arm/include/asm/assembler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <asm/opcodes-virt.h>
2222
#include <asm/asm-offsets.h>
2323
#include <asm/page.h>
24+
#include <asm/pgtable.h>
2425
#include <asm/thread_info.h>
2526
#include <asm/uaccess-asm.h>
2627

arch/arm/include/asm/glue-cache.h

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@
118118
# define MULTI_CACHE 1
119119
#endif
120120

121+
#ifdef CONFIG_CPU_CACHE_NOP
122+
# define MULTI_CACHE 1
123+
#endif
124+
121125
#if defined(CONFIG_CPU_V7M)
122126
# define MULTI_CACHE 1
123127
#endif
@@ -126,29 +130,15 @@
126130
#error Unknown cache maintenance model
127131
#endif
128132

129-
#ifndef __ASSEMBLER__
130-
static inline void nop_flush_icache_all(void) { }
131-
static inline void nop_flush_kern_cache_all(void) { }
132-
static inline void nop_flush_kern_cache_louis(void) { }
133-
static inline void nop_flush_user_cache_all(void) { }
134-
static inline void nop_flush_user_cache_range(unsigned long a,
135-
unsigned long b, unsigned int c) { }
136-
137-
static inline void nop_coherent_kern_range(unsigned long a, unsigned long b) { }
138-
static inline int nop_coherent_user_range(unsigned long a,
139-
unsigned long b) { return 0; }
140-
static inline void nop_flush_kern_dcache_area(void *a, size_t s) { }
141-
142-
static inline void nop_dma_flush_range(const void *a, const void *b) { }
143-
144-
static inline void nop_dma_map_area(const void *s, size_t l, int f) { }
145-
static inline void nop_dma_unmap_area(const void *s, size_t l, int f) { }
146-
#endif
147-
148133
#ifndef MULTI_CACHE
149134
#define __cpuc_flush_icache_all __glue(_CACHE,_flush_icache_all)
150135
#define __cpuc_flush_kern_all __glue(_CACHE,_flush_kern_cache_all)
136+
/* This function only has a dedicated assembly callback on the v7 cache */
137+
#ifdef CONFIG_CPU_CACHE_V7
151138
#define __cpuc_flush_kern_louis __glue(_CACHE,_flush_kern_cache_louis)
139+
#else
140+
#define __cpuc_flush_kern_louis __glue(_CACHE,_flush_kern_cache_all)
141+
#endif
152142
#define __cpuc_flush_user_all __glue(_CACHE,_flush_user_cache_all)
153143
#define __cpuc_flush_user_range __glue(_CACHE,_flush_user_cache_range)
154144
#define __cpuc_coherent_kern_range __glue(_CACHE,_coherent_kern_range)

arch/arm/include/asm/hw_breakpoint.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ static inline void decode_ctrl_reg(u32 reg,
8484
#define ARM_DSCR_MOE(x) ((x >> 2) & 0xf)
8585
#define ARM_ENTRY_BREAKPOINT 0x1
8686
#define ARM_ENTRY_ASYNC_WATCHPOINT 0x2
87+
#define ARM_ENTRY_CFI_BREAKPOINT 0x3
8788
#define ARM_ENTRY_SYNC_WATCHPOINT 0xa
8889

8990
/* DSCR monitor/halting bits. */

arch/arm/include/asm/pgtable-3level-hwdef.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
#define PHYS_MASK_SHIFT (40)
7575
#define PHYS_MASK ((1ULL << PHYS_MASK_SHIFT) - 1)
7676

77+
#ifndef CONFIG_CPU_TTBR0_PAN
7778
/*
7879
* TTBR0/TTBR1 split (PAGE_OFFSET):
7980
* 0x40000000: T0SZ = 2, T1SZ = 0 (not used)
@@ -93,5 +94,30 @@
9394
#endif
9495

9596
#define TTBR1_SIZE (((PAGE_OFFSET >> 30) - 1) << 16)
97+
#else
98+
/*
99+
* With CONFIG_CPU_TTBR0_PAN enabled, TTBR1 is only used during uaccess
100+
* disabled regions when TTBR0 is disabled.
101+
*/
102+
#define TTBR1_OFFSET 0 /* pointing to swapper_pg_dir */
103+
#define TTBR1_SIZE 0 /* TTBR1 size controlled via TTBCR.T0SZ */
104+
#endif
105+
106+
/*
107+
* TTBCR register bits.
108+
*/
109+
#define TTBCR_EAE (1 << 31)
110+
#define TTBCR_IMP (1 << 30)
111+
#define TTBCR_SH1_MASK (3 << 28)
112+
#define TTBCR_ORGN1_MASK (3 << 26)
113+
#define TTBCR_IRGN1_MASK (3 << 24)
114+
#define TTBCR_EPD1 (1 << 23)
115+
#define TTBCR_A1 (1 << 22)
116+
#define TTBCR_T1SZ_MASK (7 << 16)
117+
#define TTBCR_SH0_MASK (3 << 12)
118+
#define TTBCR_ORGN0_MASK (3 << 10)
119+
#define TTBCR_IRGN0_MASK (3 << 8)
120+
#define TTBCR_EPD0 (1 << 7)
121+
#define TTBCR_T0SZ_MASK (7 << 0)
96122

97123
#endif

arch/arm/include/asm/proc-fns.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,18 @@ extern void cpu_resume(void);
178178
})
179179
#endif
180180

181+
static inline unsigned int cpu_get_ttbcr(void)
182+
{
183+
unsigned int ttbcr;
184+
asm("mrc p15, 0, %0, c2, c0, 2" : "=r" (ttbcr));
185+
return ttbcr;
186+
}
187+
188+
static inline void cpu_set_ttbcr(unsigned int ttbcr)
189+
{
190+
asm volatile("mcr p15, 0, %0, c2, c0, 2" : : "r" (ttbcr) : "memory");
191+
}
192+
181193
#else /*!CONFIG_MMU */
182194

183195
#define cpu_switch_mm(pgd,mm) { }

arch/arm/include/asm/ptrace.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ struct pt_regs {
2020
struct svc_pt_regs {
2121
struct pt_regs regs;
2222
u32 dacr;
23+
u32 ttbcr;
2324
};
2425

2526
#define to_svc_pt_regs(r) container_of(r, struct svc_pt_regs, regs)

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

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,9 @@
3939
#endif
4040
.endm
4141

42+
#if defined(CONFIG_CPU_SW_DOMAIN_PAN)
43+
4244
.macro uaccess_disable, tmp, isb=1
43-
#ifdef CONFIG_CPU_SW_DOMAIN_PAN
4445
/*
4546
* Whenever we re-enter userspace, the domains should always be
4647
* set appropriately.
@@ -50,11 +51,9 @@
5051
.if \isb
5152
instr_sync
5253
.endif
53-
#endif
5454
.endm
5555

5656
.macro uaccess_enable, tmp, isb=1
57-
#ifdef CONFIG_CPU_SW_DOMAIN_PAN
5857
/*
5958
* Whenever we re-enter userspace, the domains should always be
6059
* set appropriately.
@@ -64,13 +63,59 @@
6463
.if \isb
6564
instr_sync
6665
.endif
67-
#endif
6866
.endm
6967

68+
#elif defined(CONFIG_CPU_TTBR0_PAN)
69+
70+
.macro uaccess_disable, tmp, isb=1
71+
/*
72+
* Disable TTBR0 page table walks (EDP0 = 1), use the reserved ASID
73+
* from TTBR1 (A1 = 1) and enable TTBR1 page table walks for kernel
74+
* addresses by reducing TTBR0 range to 32MB (T0SZ = 7).
75+
*/
76+
mrc p15, 0, \tmp, c2, c0, 2 @ read TTBCR
77+
orr \tmp, \tmp, #TTBCR_EPD0 | TTBCR_T0SZ_MASK
78+
orr \tmp, \tmp, #TTBCR_A1
79+
mcr p15, 0, \tmp, c2, c0, 2 @ write TTBCR
80+
.if \isb
81+
instr_sync
82+
.endif
83+
.endm
84+
85+
.macro uaccess_enable, tmp, isb=1
86+
/*
87+
* Enable TTBR0 page table walks (T0SZ = 0, EDP0 = 0) and ASID from
88+
* TTBR0 (A1 = 0).
89+
*/
90+
mrc p15, 0, \tmp, c2, c0, 2 @ read TTBCR
91+
bic \tmp, \tmp, #TTBCR_EPD0 | TTBCR_T0SZ_MASK
92+
bic \tmp, \tmp, #TTBCR_A1
93+
mcr p15, 0, \tmp, c2, c0, 2 @ write TTBCR
94+
.if \isb
95+
instr_sync
96+
.endif
97+
.endm
98+
99+
#else
100+
101+
.macro uaccess_disable, tmp, isb=1
102+
.endm
103+
104+
.macro uaccess_enable, tmp, isb=1
105+
.endm
106+
107+
#endif
108+
70109
#if defined(CONFIG_CPU_SW_DOMAIN_PAN) || defined(CONFIG_CPU_USE_DOMAINS)
71110
#define DACR(x...) x
72111
#else
73112
#define DACR(x...)
113+
#endif
114+
115+
#ifdef CONFIG_CPU_TTBR0_PAN
116+
#define PAN(x...) x
117+
#else
118+
#define PAN(x...)
74119
#endif
75120

76121
/*
@@ -86,6 +131,8 @@
86131
.macro uaccess_entry, tsk, tmp0, tmp1, tmp2, disable
87132
DACR( mrc p15, 0, \tmp0, c3, c0, 0)
88133
DACR( str \tmp0, [sp, #SVC_DACR])
134+
PAN( mrc p15, 0, \tmp0, c2, c0, 2)
135+
PAN( str \tmp0, [sp, #SVC_TTBCR])
89136
.if \disable && IS_ENABLED(CONFIG_CPU_SW_DOMAIN_PAN)
90137
/* kernel=client, user=no access */
91138
mov \tmp2, #DACR_UACCESS_DISABLE
@@ -104,8 +151,11 @@
104151
.macro uaccess_exit, tsk, tmp0, tmp1
105152
DACR( ldr \tmp0, [sp, #SVC_DACR])
106153
DACR( mcr p15, 0, \tmp0, c3, c0, 0)
154+
PAN( ldr \tmp0, [sp, #SVC_TTBCR])
155+
PAN( mcr p15, 0, \tmp0, c2, c0, 2)
107156
.endm
108157

109158
#undef DACR
159+
#undef PAN
110160

111161
#endif /* __ASM_UACCESS_ASM_H__ */

arch/arm/include/asm/uaccess.h

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
#include <asm/domain.h>
1515
#include <asm/unaligned.h>
1616
#include <asm/unified.h>
17+
#include <asm/pgtable.h>
18+
#include <asm/proc-fns.h>
1719
#include <asm/compiler.h>
1820

1921
#include <asm/extable.h>
@@ -24,29 +26,60 @@
2426
* perform such accesses (eg, via list poison values) which could then
2527
* be exploited for priviledge escalation.
2628
*/
29+
#if defined(CONFIG_CPU_SW_DOMAIN_PAN)
30+
2731
static __always_inline unsigned int uaccess_save_and_enable(void)
2832
{
29-
#ifdef CONFIG_CPU_SW_DOMAIN_PAN
3033
unsigned int old_domain = get_domain();
3134

3235
/* Set the current domain access to permit user accesses */
3336
set_domain((old_domain & ~domain_mask(DOMAIN_USER)) |
3437
domain_val(DOMAIN_USER, DOMAIN_CLIENT));
3538

3639
return old_domain;
37-
#else
38-
return 0;
39-
#endif
4040
}
4141

4242
static __always_inline void uaccess_restore(unsigned int flags)
4343
{
44-
#ifdef CONFIG_CPU_SW_DOMAIN_PAN
4544
/* Restore the user access mask */
4645
set_domain(flags);
47-
#endif
4846
}
4947

48+
#elif defined(CONFIG_CPU_TTBR0_PAN)
49+
50+
static __always_inline unsigned int uaccess_save_and_enable(void)
51+
{
52+
unsigned int old_ttbcr = cpu_get_ttbcr();
53+
54+
/*
55+
* Enable TTBR0 page table walks (T0SZ = 0, EDP0 = 0) and ASID from
56+
* TTBR0 (A1 = 0).
57+
*/
58+
cpu_set_ttbcr(old_ttbcr & ~(TTBCR_A1 | TTBCR_EPD0 | TTBCR_T0SZ_MASK));
59+
isb();
60+
61+
return old_ttbcr;
62+
}
63+
64+
static inline void uaccess_restore(unsigned int flags)
65+
{
66+
cpu_set_ttbcr(flags);
67+
isb();
68+
}
69+
70+
#else
71+
72+
static inline unsigned int uaccess_save_and_enable(void)
73+
{
74+
return 0;
75+
}
76+
77+
static inline void uaccess_restore(unsigned int flags)
78+
{
79+
}
80+
81+
#endif
82+
5083
/*
5184
* These two are intentionally not defined anywhere - if the kernel
5285
* code generates any references to them, that's a bug.

arch/arm/kernel/asm-offsets.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ int main(void)
8585
DEFINE(S_OLD_R0, offsetof(struct pt_regs, ARM_ORIG_r0));
8686
DEFINE(PT_REGS_SIZE, sizeof(struct pt_regs));
8787
DEFINE(SVC_DACR, offsetof(struct svc_pt_regs, dacr));
88+
DEFINE(SVC_TTBCR, offsetof(struct svc_pt_regs, ttbcr));
8889
DEFINE(SVC_REGS_SIZE, sizeof(struct svc_pt_regs));
8990
BLANK();
9091
DEFINE(SIGFRAME_RC3_OFFSET, offsetof(struct sigframe, retcode[3]));

0 commit comments

Comments
 (0)