Skip to content

Commit 81fd9c1

Browse files
thejhKAGA-KOKO
authored andcommitted
x86/fault: Plumb error code and fault address through to fault handlers
This is preparation for looking at trap number and fault address in the handlers for uaccess errors. No functional change. Signed-off-by: Jann Horn <jannh@google.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Tested-by: Kees Cook <keescook@chromium.org> Cc: Andy Lutomirski <luto@kernel.org> Cc: kernel-hardening@lists.openwall.com Cc: linux-kernel@vger.kernel.org Cc: dvyukov@google.com Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: "Naveen N. Rao" <naveen.n.rao@linux.vnet.ibm.com> Cc: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> Cc: "David S. Miller" <davem@davemloft.net> Cc: Alexander Viro <viro@zeniv.linux.org.uk> Cc: linux-fsdevel@vger.kernel.org Cc: Borislav Petkov <bp@alien8.de> Link: https://lkml.kernel.org/r/20180828201421.157735-6-jannh@google.com
1 parent 75045f7 commit 81fd9c1

File tree

6 files changed

+44
-21
lines changed

6 files changed

+44
-21
lines changed

arch/x86/include/asm/extable.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ struct pt_regs;
2929
(b)->handler = (tmp).handler - (delta); \
3030
} while (0)
3131

32-
extern int fixup_exception(struct pt_regs *regs, int trapnr);
32+
extern int fixup_exception(struct pt_regs *regs, int trapnr,
33+
unsigned long error_code, unsigned long fault_addr);
3334
extern int fixup_bug(struct pt_regs *regs, int trapnr);
3435
extern bool ex_has_fault_handler(unsigned long ip);
3536
extern void early_fixup_exception(struct pt_regs *regs, int trapnr);

arch/x86/include/asm/ptrace.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,10 @@ struct pt_regs {
3737
unsigned short __esh;
3838
unsigned short fs;
3939
unsigned short __fsh;
40+
/* On interrupt, gs and __gsh store the vector number. */
4041
unsigned short gs;
4142
unsigned short __gsh;
43+
/* On interrupt, this is the error code. */
4244
unsigned long orig_ax;
4345
unsigned long ip;
4446
unsigned short cs;

arch/x86/kernel/cpu/mcheck/mce.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1315,7 +1315,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
13151315
local_irq_disable();
13161316
ist_end_non_atomic();
13171317
} else {
1318-
if (!fixup_exception(regs, X86_TRAP_MC))
1318+
if (!fixup_exception(regs, X86_TRAP_MC, error_code, 0))
13191319
mce_panic("Failed kernel mode recovery", &m, NULL);
13201320
}
13211321

arch/x86/kernel/traps.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ do_trap_no_signal(struct task_struct *tsk, int trapnr, char *str,
206206
}
207207

208208
if (!user_mode(regs)) {
209-
if (fixup_exception(regs, trapnr))
209+
if (fixup_exception(regs, trapnr, error_code, 0))
210210
return 0;
211211

212212
tsk->thread.error_code = error_code;
@@ -551,7 +551,7 @@ do_general_protection(struct pt_regs *regs, long error_code)
551551

552552
tsk = current;
553553
if (!user_mode(regs)) {
554-
if (fixup_exception(regs, X86_TRAP_GP))
554+
if (fixup_exception(regs, X86_TRAP_GP, error_code, 0))
555555
return;
556556

557557
tsk->thread.error_code = error_code;
@@ -848,7 +848,7 @@ static void math_error(struct pt_regs *regs, int error_code, int trapnr)
848848
cond_local_irq_enable(regs);
849849

850850
if (!user_mode(regs)) {
851-
if (fixup_exception(regs, trapnr))
851+
if (fixup_exception(regs, trapnr, error_code, 0))
852852
return;
853853

854854
task->thread.error_code = error_code;

arch/x86/mm/extable.c

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
#include <asm/kdebug.h>
99

1010
typedef bool (*ex_handler_t)(const struct exception_table_entry *,
11-
struct pt_regs *, int);
11+
struct pt_regs *, int, unsigned long,
12+
unsigned long);
1213

1314
static inline unsigned long
1415
ex_fixup_addr(const struct exception_table_entry *x)
@@ -22,15 +23,19 @@ ex_fixup_handler(const struct exception_table_entry *x)
2223
}
2324

2425
__visible bool ex_handler_default(const struct exception_table_entry *fixup,
25-
struct pt_regs *regs, int trapnr)
26+
struct pt_regs *regs, int trapnr,
27+
unsigned long error_code,
28+
unsigned long fault_addr)
2629
{
2730
regs->ip = ex_fixup_addr(fixup);
2831
return true;
2932
}
3033
EXPORT_SYMBOL(ex_handler_default);
3134

3235
__visible bool ex_handler_fault(const struct exception_table_entry *fixup,
33-
struct pt_regs *regs, int trapnr)
36+
struct pt_regs *regs, int trapnr,
37+
unsigned long error_code,
38+
unsigned long fault_addr)
3439
{
3540
regs->ip = ex_fixup_addr(fixup);
3641
regs->ax = trapnr;
@@ -43,7 +48,9 @@ EXPORT_SYMBOL_GPL(ex_handler_fault);
4348
* result of a refcount inc/dec/add/sub.
4449
*/
4550
__visible bool ex_handler_refcount(const struct exception_table_entry *fixup,
46-
struct pt_regs *regs, int trapnr)
51+
struct pt_regs *regs, int trapnr,
52+
unsigned long error_code,
53+
unsigned long fault_addr)
4754
{
4855
/* First unconditionally saturate the refcount. */
4956
*(int *)regs->cx = INT_MIN / 2;
@@ -96,7 +103,9 @@ EXPORT_SYMBOL(ex_handler_refcount);
96103
* out all the FPU registers) if we can't restore from the task's FPU state.
97104
*/
98105
__visible bool ex_handler_fprestore(const struct exception_table_entry *fixup,
99-
struct pt_regs *regs, int trapnr)
106+
struct pt_regs *regs, int trapnr,
107+
unsigned long error_code,
108+
unsigned long fault_addr)
100109
{
101110
regs->ip = ex_fixup_addr(fixup);
102111

@@ -109,15 +118,19 @@ __visible bool ex_handler_fprestore(const struct exception_table_entry *fixup,
109118
EXPORT_SYMBOL_GPL(ex_handler_fprestore);
110119

111120
__visible bool ex_handler_uaccess(const struct exception_table_entry *fixup,
112-
struct pt_regs *regs, int trapnr)
121+
struct pt_regs *regs, int trapnr,
122+
unsigned long error_code,
123+
unsigned long fault_addr)
113124
{
114125
regs->ip = ex_fixup_addr(fixup);
115126
return true;
116127
}
117128
EXPORT_SYMBOL(ex_handler_uaccess);
118129

119130
__visible bool ex_handler_ext(const struct exception_table_entry *fixup,
120-
struct pt_regs *regs, int trapnr)
131+
struct pt_regs *regs, int trapnr,
132+
unsigned long error_code,
133+
unsigned long fault_addr)
121134
{
122135
/* Special hack for uaccess_err */
123136
current->thread.uaccess_err = 1;
@@ -127,7 +140,9 @@ __visible bool ex_handler_ext(const struct exception_table_entry *fixup,
127140
EXPORT_SYMBOL(ex_handler_ext);
128141

129142
__visible bool ex_handler_rdmsr_unsafe(const struct exception_table_entry *fixup,
130-
struct pt_regs *regs, int trapnr)
143+
struct pt_regs *regs, int trapnr,
144+
unsigned long error_code,
145+
unsigned long fault_addr)
131146
{
132147
if (pr_warn_once("unchecked MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pF)\n",
133148
(unsigned int)regs->cx, regs->ip, (void *)regs->ip))
@@ -142,7 +157,9 @@ __visible bool ex_handler_rdmsr_unsafe(const struct exception_table_entry *fixup
142157
EXPORT_SYMBOL(ex_handler_rdmsr_unsafe);
143158

144159
__visible bool ex_handler_wrmsr_unsafe(const struct exception_table_entry *fixup,
145-
struct pt_regs *regs, int trapnr)
160+
struct pt_regs *regs, int trapnr,
161+
unsigned long error_code,
162+
unsigned long fault_addr)
146163
{
147164
if (pr_warn_once("unchecked MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pF)\n",
148165
(unsigned int)regs->cx, (unsigned int)regs->dx,
@@ -156,12 +173,14 @@ __visible bool ex_handler_wrmsr_unsafe(const struct exception_table_entry *fixup
156173
EXPORT_SYMBOL(ex_handler_wrmsr_unsafe);
157174

158175
__visible bool ex_handler_clear_fs(const struct exception_table_entry *fixup,
159-
struct pt_regs *regs, int trapnr)
176+
struct pt_regs *regs, int trapnr,
177+
unsigned long error_code,
178+
unsigned long fault_addr)
160179
{
161180
if (static_cpu_has(X86_BUG_NULL_SEG))
162181
asm volatile ("mov %0, %%fs" : : "rm" (__USER_DS));
163182
asm volatile ("mov %0, %%fs" : : "rm" (0));
164-
return ex_handler_default(fixup, regs, trapnr);
183+
return ex_handler_default(fixup, regs, trapnr, error_code, fault_addr);
165184
}
166185
EXPORT_SYMBOL(ex_handler_clear_fs);
167186

@@ -178,7 +197,8 @@ __visible bool ex_has_fault_handler(unsigned long ip)
178197
return handler == ex_handler_fault;
179198
}
180199

181-
int fixup_exception(struct pt_regs *regs, int trapnr)
200+
int fixup_exception(struct pt_regs *regs, int trapnr, unsigned long error_code,
201+
unsigned long fault_addr)
182202
{
183203
const struct exception_table_entry *e;
184204
ex_handler_t handler;
@@ -202,7 +222,7 @@ int fixup_exception(struct pt_regs *regs, int trapnr)
202222
return 0;
203223

204224
handler = ex_fixup_handler(e);
205-
return handler(e, regs, trapnr);
225+
return handler(e, regs, trapnr, error_code, fault_addr);
206226
}
207227

208228
extern unsigned int early_recursion_flag;
@@ -238,9 +258,9 @@ void __init early_fixup_exception(struct pt_regs *regs, int trapnr)
238258
* result in a hard-to-debug panic.
239259
*
240260
* Keep in mind that not all vectors actually get here. Early
241-
* fage faults, for example, are special.
261+
* page faults, for example, are special.
242262
*/
243-
if (fixup_exception(regs, trapnr))
263+
if (fixup_exception(regs, trapnr, regs->orig_ax, 0))
244264
return;
245265

246266
if (fixup_bug(regs, trapnr))

arch/x86/mm/fault.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -711,7 +711,7 @@ no_context(struct pt_regs *regs, unsigned long error_code,
711711
int sig;
712712

713713
/* Are we prepared to handle this kernel fault? */
714-
if (fixup_exception(regs, X86_TRAP_PF)) {
714+
if (fixup_exception(regs, X86_TRAP_PF, error_code, address)) {
715715
/*
716716
* Any interrupt that takes a fault gets the fixup. This makes
717717
* the below recursive fault logic only apply to a faults from

0 commit comments

Comments
 (0)