Skip to content

Commit 19accfd

Browse files
author
Russell King
committed
ARM: move vector stubs
Move the machine vector stubs into the page above the vector page, which we can prevent from being visible to userspace. Also move the reset stub, and place the swi vector at a location that the 'ldr' can get to it. This hides pointers into the kernel which could give valuable information to attackers, and reduces the number of exploitable instructions at a fixed address. Cc: <[email protected]> Acked-by: Nicolas Pitre <[email protected]> Signed-off-by: Russell King <[email protected]>
1 parent 5b43e7a commit 19accfd

File tree

4 files changed

+37
-30
lines changed

4 files changed

+37
-30
lines changed

arch/arm/Kconfig

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,8 @@ config VECTORS_BASE
218218
default DRAM_BASE if REMAP_VECTORS_TO_RAM
219219
default 0x00000000
220220
help
221-
The base address of exception vectors.
221+
The base address of exception vectors. This must be two pages
222+
in size.
222223

223224
config ARM_PATCH_PHYS_VIRT
224225
bool "Patch physical to virtual translations at runtime" if EMBEDDED

arch/arm/kernel/entry-armv.S

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -944,9 +944,9 @@ __kuser_helper_end:
944944
/*
945945
* Vector stubs.
946946
*
947-
* This code is copied to 0xffff0200 so we can use branches in the
948-
* vectors, rather than ldr's. Note that this code must not
949-
* exceed 0x300 bytes.
947+
* This code is copied to 0xffff1000 so we can use branches in the
948+
* vectors, rather than ldr's. Note that this code must not exceed
949+
* a page size.
950950
*
951951
* Common stub entry macro:
952952
* Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
@@ -995,6 +995,15 @@ ENDPROC(vector_\name)
995995

996996
.globl __stubs_start
997997
__stubs_start:
998+
@ This must be the first word
999+
.word vector_swi
1000+
1001+
vector_rst:
1002+
ARM( swi SYS_ERROR0 )
1003+
THUMB( svc #0 )
1004+
THUMB( nop )
1005+
b vector_und
1006+
9981007
/*
9991008
* Interrupt dispatcher
10001009
*/
@@ -1088,6 +1097,16 @@ __stubs_start:
10881097

10891098
.align 5
10901099

1100+
/*=============================================================================
1101+
* Address exception handler
1102+
*-----------------------------------------------------------------------------
1103+
* These aren't too critical.
1104+
* (they're not supposed to happen, and won't happen in 32-bit data mode).
1105+
*/
1106+
1107+
vector_addrexcptn:
1108+
b vector_addrexcptn
1109+
10911110
/*=============================================================================
10921111
* Undefined FIQs
10931112
*-----------------------------------------------------------------------------
@@ -1101,35 +1120,14 @@ __stubs_start:
11011120
vector_fiq:
11021121
subs pc, lr, #4
11031122

1104-
/*=============================================================================
1105-
* Address exception handler
1106-
*-----------------------------------------------------------------------------
1107-
* These aren't too critical.
1108-
* (they're not supposed to happen, and won't happen in 32-bit data mode).
1109-
*/
1110-
1111-
vector_addrexcptn:
1112-
b vector_addrexcptn
1113-
1114-
/*
1115-
* We group all the following data together to optimise
1116-
* for CPUs with separate I & D caches.
1117-
*/
1118-
.align 5
1119-
1120-
.LCvswi:
1121-
.word vector_swi
1122-
11231123
.globl __stubs_end
11241124
__stubs_end:
11251125

1126-
.equ stubs_offset, __vectors_start + 0x200 - __stubs_start
1126+
.equ stubs_offset, __vectors_start + 0x1000 - __stubs_start
11271127

11281128
.globl __vectors_start
11291129
__vectors_start:
1130-
ARM( swi SYS_ERROR0 )
1131-
THUMB( svc #0 )
1132-
THUMB( nop )
1130+
W(b) vector_rst + stubs_offset
11331131
W(b) vector_und + stubs_offset
11341132
W(ldr) pc, .LCvswi + stubs_offset
11351133
W(b) vector_pabt + stubs_offset

arch/arm/kernel/traps.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -837,7 +837,7 @@ void __init early_trap_init(void *vectors_base)
837837
* are visible to the instruction stream.
838838
*/
839839
memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);
840-
memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start);
840+
memcpy((void *)vectors + 0x1000, __stubs_start, __stubs_end - __stubs_start);
841841
memcpy((void *)vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz);
842842

843843
/*
@@ -852,7 +852,7 @@ void __init early_trap_init(void *vectors_base)
852852
memcpy((void *)(vectors + KERN_SIGRETURN_CODE - CONFIG_VECTORS_BASE),
853853
sigreturn_codes, sizeof(sigreturn_codes));
854854

855-
flush_icache_range(vectors, vectors + PAGE_SIZE);
855+
flush_icache_range(vectors, vectors + PAGE_SIZE * 2);
856856
modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
857857
#else /* ifndef CONFIG_CPU_V7M */
858858
/*

arch/arm/mm/mmu.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1160,7 +1160,7 @@ static void __init devicemaps_init(struct machine_desc *mdesc)
11601160
/*
11611161
* Allocate the vector page early.
11621162
*/
1163-
vectors = early_alloc(PAGE_SIZE);
1163+
vectors = early_alloc(PAGE_SIZE * 2);
11641164

11651165
early_trap_init(vectors);
11661166

@@ -1210,10 +1210,18 @@ static void __init devicemaps_init(struct machine_desc *mdesc)
12101210

12111211
if (!vectors_high()) {
12121212
map.virtual = 0;
1213+
map.length = PAGE_SIZE * 2;
12131214
map.type = MT_LOW_VECTORS;
12141215
create_mapping(&map);
12151216
}
12161217

1218+
/* Now create a kernel read-only mapping */
1219+
map.pfn += 1;
1220+
map.virtual = 0xffff0000 + PAGE_SIZE;
1221+
map.length = PAGE_SIZE;
1222+
map.type = MT_LOW_VECTORS;
1223+
create_mapping(&map);
1224+
12171225
/*
12181226
* Ask the machine support to map in the statically mapped devices.
12191227
*/

0 commit comments

Comments
 (0)