Skip to content

Commit

Permalink
ARM: save and reset the address limit when entering an exception
Browse files Browse the repository at this point in the history
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 <will.deacon@arm.com>
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
  • Loading branch information
Russell King committed Jul 7, 2016
1 parent dd665be commit e6978e4
Show file tree
Hide file tree
Showing 5 changed files with 20 additions and 6 deletions.
2 changes: 1 addition & 1 deletion arch/arm/include/asm/ptrace.h
Expand Up @@ -22,7 +22,7 @@ struct pt_regs {
struct svc_pt_regs {
struct pt_regs regs;
u32 dacr;
u32 unused;
u32 addr_limit;
};

#define to_svc_pt_regs(r) container_of(r, struct svc_pt_regs, regs)
Expand Down
1 change: 1 addition & 0 deletions arch/arm/kernel/asm-offsets.c
Expand Up @@ -109,6 +109,7 @@ int main(void)
DEFINE(S_OLD_R0, offsetof(struct pt_regs, ARM_ORIG_r0));
DEFINE(PT_REGS_SIZE, sizeof(struct pt_regs));
DEFINE(SVC_DACR, offsetof(struct svc_pt_regs, dacr));
DEFINE(SVC_ADDR_LIMIT, offsetof(struct svc_pt_regs, addr_limit));
DEFINE(SVC_REGS_SIZE, sizeof(struct svc_pt_regs));
BLANK();
#ifdef CONFIG_CACHE_L2X0
Expand Down
7 changes: 6 additions & 1 deletion arch/arm/kernel/entry-armv.S
Expand Up @@ -185,6 +185,12 @@ ENDPROC(__und_invalid)
@
stmia r7, {r2 - r6}

get_thread_info tsk
ldr r0, [tsk, #TI_ADDR_LIMIT]
mov r1, #TASK_SIZE
str r1, [tsk, #TI_ADDR_LIMIT]
str r0, [sp, #SVC_ADDR_LIMIT]

uaccess_save r0
.if \uaccess
uaccess_disable r0
Expand Down Expand Up @@ -213,7 +219,6 @@ __irq_svc:
irq_handler

#ifdef CONFIG_PREEMPT
get_thread_info tsk
ldr r8, [tsk, #TI_PREEMPT] @ get preempt count
ldr r0, [tsk, #TI_FLAGS] @ get flags
teq r8, #0 @ if preempt count != 0
Expand Down
4 changes: 4 additions & 0 deletions arch/arm/kernel/entry-header.S
Expand Up @@ -215,7 +215,9 @@
blne trace_hardirqs_off
#endif
.endif
ldr r1, [sp, #SVC_ADDR_LIMIT]
uaccess_restore
str r1, [tsk, #TI_ADDR_LIMIT]

#ifndef CONFIG_THUMB2_KERNEL
@ ARM mode SVC restore
Expand Down Expand Up @@ -259,7 +261,9 @@
@ on the stack remains correct).
@
.macro svc_exit_via_fiq
ldr r1, [sp, #SVC_ADDR_LIMIT]
uaccess_restore
str r1, [tsk, #TI_ADDR_LIMIT]
#ifndef CONFIG_THUMB2_KERNEL
@ ARM mode restore
mov r0, sp
Expand Down
12 changes: 8 additions & 4 deletions arch/arm/kernel/process.c
Expand Up @@ -96,19 +96,23 @@ void __show_regs(struct pt_regs *regs)
unsigned long flags;
char buf[64];
#ifndef CONFIG_CPU_V7M
unsigned int domain;
unsigned int domain, fs;
#ifdef CONFIG_CPU_SW_DOMAIN_PAN
/*
* Get the domain register for the parent context. In user
* mode, we don't save the DACR, so lets use what it should
* be. For other modes, we place it after the pt_regs struct.
*/
if (user_mode(regs))
if (user_mode(regs)) {
domain = DACR_UACCESS_ENABLE;
else
fs = get_fs();
} else {
domain = to_svc_pt_regs(regs)->dacr;
fs = to_svc_pt_regs(regs)->addr_limit;
}
#else
domain = get_domain();
fs = get_fs();
#endif
#endif

Expand Down Expand Up @@ -144,7 +148,7 @@ void __show_regs(struct pt_regs *regs)
if ((domain & domain_mask(DOMAIN_USER)) ==
domain_val(DOMAIN_USER, DOMAIN_NOACCESS))
segment = "none";
else if (get_fs() == get_ds())
else if (fs == get_ds())
segment = "kernel";
else
segment = "user";
Expand Down

0 comments on commit e6978e4

Please sign in to comment.