Skip to content

Commit e6978e4

Browse files
author
Russell King
committed
ARM: save and reset the address limit when entering an exception
When we enter an exception, the current address limit should not apply to the exception context: if the exception context wishes to access kernel space via the user accessors (eg, perf code), it must explicitly request such access. Acked-by: Will Deacon <[email protected]> Signed-off-by: Russell King <[email protected]>
1 parent dd665be commit e6978e4

File tree

5 files changed

+20
-6
lines changed

5 files changed

+20
-6
lines changed

arch/arm/include/asm/ptrace.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ struct pt_regs {
2222
struct svc_pt_regs {
2323
struct pt_regs regs;
2424
u32 dacr;
25-
u32 unused;
25+
u32 addr_limit;
2626
};
2727

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

arch/arm/kernel/asm-offsets.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ int main(void)
109109
DEFINE(S_OLD_R0, offsetof(struct pt_regs, ARM_ORIG_r0));
110110
DEFINE(PT_REGS_SIZE, sizeof(struct pt_regs));
111111
DEFINE(SVC_DACR, offsetof(struct svc_pt_regs, dacr));
112+
DEFINE(SVC_ADDR_LIMIT, offsetof(struct svc_pt_regs, addr_limit));
112113
DEFINE(SVC_REGS_SIZE, sizeof(struct svc_pt_regs));
113114
BLANK();
114115
#ifdef CONFIG_CACHE_L2X0

arch/arm/kernel/entry-armv.S

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,12 @@ ENDPROC(__und_invalid)
185185
@
186186
stmia r7, {r2 - r6}
187187

188+
get_thread_info tsk
189+
ldr r0, [tsk, #TI_ADDR_LIMIT]
190+
mov r1, #TASK_SIZE
191+
str r1, [tsk, #TI_ADDR_LIMIT]
192+
str r0, [sp, #SVC_ADDR_LIMIT]
193+
188194
uaccess_save r0
189195
.if \uaccess
190196
uaccess_disable r0
@@ -213,7 +219,6 @@ __irq_svc:
213219
irq_handler
214220

215221
#ifdef CONFIG_PREEMPT
216-
get_thread_info tsk
217222
ldr r8, [tsk, #TI_PREEMPT] @ get preempt count
218223
ldr r0, [tsk, #TI_FLAGS] @ get flags
219224
teq r8, #0 @ if preempt count != 0

arch/arm/kernel/entry-header.S

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,9 @@
215215
blne trace_hardirqs_off
216216
#endif
217217
.endif
218+
ldr r1, [sp, #SVC_ADDR_LIMIT]
218219
uaccess_restore
220+
str r1, [tsk, #TI_ADDR_LIMIT]
219221

220222
#ifndef CONFIG_THUMB2_KERNEL
221223
@ ARM mode SVC restore
@@ -259,7 +261,9 @@
259261
@ on the stack remains correct).
260262
@
261263
.macro svc_exit_via_fiq
264+
ldr r1, [sp, #SVC_ADDR_LIMIT]
262265
uaccess_restore
266+
str r1, [tsk, #TI_ADDR_LIMIT]
263267
#ifndef CONFIG_THUMB2_KERNEL
264268
@ ARM mode restore
265269
mov r0, sp

arch/arm/kernel/process.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,19 +96,23 @@ void __show_regs(struct pt_regs *regs)
9696
unsigned long flags;
9797
char buf[64];
9898
#ifndef CONFIG_CPU_V7M
99-
unsigned int domain;
99+
unsigned int domain, fs;
100100
#ifdef CONFIG_CPU_SW_DOMAIN_PAN
101101
/*
102102
* Get the domain register for the parent context. In user
103103
* mode, we don't save the DACR, so lets use what it should
104104
* be. For other modes, we place it after the pt_regs struct.
105105
*/
106-
if (user_mode(regs))
106+
if (user_mode(regs)) {
107107
domain = DACR_UACCESS_ENABLE;
108-
else
108+
fs = get_fs();
109+
} else {
109110
domain = to_svc_pt_regs(regs)->dacr;
111+
fs = to_svc_pt_regs(regs)->addr_limit;
112+
}
110113
#else
111114
domain = get_domain();
115+
fs = get_fs();
112116
#endif
113117
#endif
114118

@@ -144,7 +148,7 @@ void __show_regs(struct pt_regs *regs)
144148
if ((domain & domain_mask(DOMAIN_USER)) ==
145149
domain_val(DOMAIN_USER, DOMAIN_NOACCESS))
146150
segment = "none";
147-
else if (get_fs() == get_ds())
151+
else if (fs == get_ds())
148152
segment = "kernel";
149153
else
150154
segment = "user";

0 commit comments

Comments
 (0)