diff options
author | Russell King <rmk+kernel@armlinux.org.uk> | 2016-05-13 06:40:20 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@armlinux.org.uk> | 2016-07-07 11:01:01 -0400 |
commit | e6978e4bf181fb3b5f8cb6f71b4fe30fbf1b655c (patch) | |
tree | dddb20dbc9a5e594e406e71ed598039b33e0a4be /arch/arm/kernel/process.c | |
parent | dd665be0e243873343a28e18f9f345927b658daf (diff) |
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 <will.deacon@arm.com>
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Diffstat (limited to 'arch/arm/kernel/process.c')
-rw-r--r-- | arch/arm/kernel/process.c | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index f1c720c0d568..612eb530f33f 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c | |||
@@ -96,19 +96,23 @@ void __show_regs(struct pt_regs *regs) | |||
96 | unsigned long flags; | 96 | unsigned long flags; |
97 | char buf[64]; | 97 | char buf[64]; |
98 | #ifndef CONFIG_CPU_V7M | 98 | #ifndef CONFIG_CPU_V7M |
99 | unsigned int domain; | 99 | unsigned int domain, fs; |
100 | #ifdef CONFIG_CPU_SW_DOMAIN_PAN | 100 | #ifdef CONFIG_CPU_SW_DOMAIN_PAN |
101 | /* | 101 | /* |
102 | * Get the domain register for the parent context. In user | 102 | * Get the domain register for the parent context. In user |
103 | * mode, we don't save the DACR, so lets use what it should | 103 | * mode, we don't save the DACR, so lets use what it should |
104 | * be. For other modes, we place it after the pt_regs struct. | 104 | * be. For other modes, we place it after the pt_regs struct. |
105 | */ | 105 | */ |
106 | if (user_mode(regs)) | 106 | if (user_mode(regs)) { |
107 | domain = DACR_UACCESS_ENABLE; | 107 | domain = DACR_UACCESS_ENABLE; |
108 | else | 108 | fs = get_fs(); |
109 | } else { | ||
109 | domain = to_svc_pt_regs(regs)->dacr; | 110 | domain = to_svc_pt_regs(regs)->dacr; |
111 | fs = to_svc_pt_regs(regs)->addr_limit; | ||
112 | } | ||
110 | #else | 113 | #else |
111 | domain = get_domain(); | 114 | domain = get_domain(); |
115 | fs = get_fs(); | ||
112 | #endif | 116 | #endif |
113 | #endif | 117 | #endif |
114 | 118 | ||
@@ -144,7 +148,7 @@ void __show_regs(struct pt_regs *regs) | |||
144 | if ((domain & domain_mask(DOMAIN_USER)) == | 148 | if ((domain & domain_mask(DOMAIN_USER)) == |
145 | domain_val(DOMAIN_USER, DOMAIN_NOACCESS)) | 149 | domain_val(DOMAIN_USER, DOMAIN_NOACCESS)) |
146 | segment = "none"; | 150 | segment = "none"; |
147 | else if (get_fs() == get_ds()) | 151 | else if (fs == get_ds()) |
148 | segment = "kernel"; | 152 | segment = "kernel"; |
149 | else | 153 | else |
150 | segment = "user"; | 154 | segment = "user"; |