Skip to content

Commit 278b917

Browse files
youquan-songsuryasaimadhu
authored andcommitted
x86/mce: Add _ASM_EXTABLE_CPY for copy user access
_ASM_EXTABLE_UA is a general exception entry to record the exception fixup for all exception spots between kernel and user space access. To enable recovery from machine checks while coping data from user addresses it is necessary to be able to distinguish the places that are looping copying data from those that copy a single byte/word/etc. Add a new macro _ASM_EXTABLE_CPY and use it in place of _ASM_EXTABLE_UA in the copy functions. Record the exception reason number to regs->ax at ex_handler_uaccess which is used to check MCE triggered. The new fixup routine ex_handler_copy() is almost an exact copy of ex_handler_uaccess() The difference is that it sets regs->ax to the trap number. Following patches use this to avoid trying to copy remaining bytes from the tail of the copy and possibly hitting the poison again. New mce.kflags bit MCE_IN_KERNEL_COPYIN will be used by mce_severity() calculation to indicate that a machine check is recoverable because the kernel was copying from user space. Signed-off-by: Youquan Song <youquan.song@intel.com> Signed-off-by: Tony Luck <tony.luck@intel.com> Signed-off-by: Borislav Petkov <bp@suse.de> Link: https://lkml.kernel.org/r/20201006210910.21062-4-tony.luck@intel.com
1 parent a05d54c commit 278b917

4 files changed

Lines changed: 82 additions & 49 deletions

File tree

arch/x86/include/asm/asm.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,9 @@
135135
# define _ASM_EXTABLE_UA(from, to) \
136136
_ASM_EXTABLE_HANDLE(from, to, ex_handler_uaccess)
137137

138+
# define _ASM_EXTABLE_CPY(from, to) \
139+
_ASM_EXTABLE_HANDLE(from, to, ex_handler_copy)
140+
138141
# define _ASM_EXTABLE_FAULT(from, to) \
139142
_ASM_EXTABLE_HANDLE(from, to, ex_handler_fault)
140143

@@ -160,6 +163,9 @@
160163
# define _ASM_EXTABLE_UA(from, to) \
161164
_ASM_EXTABLE_HANDLE(from, to, ex_handler_uaccess)
162165

166+
# define _ASM_EXTABLE_CPY(from, to) \
167+
_ASM_EXTABLE_HANDLE(from, to, ex_handler_copy)
168+
163169
# define _ASM_EXTABLE_FAULT(from, to) \
164170
_ASM_EXTABLE_HANDLE(from, to, ex_handler_fault)
165171

arch/x86/include/asm/mce.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,23 @@
136136
#define MCE_HANDLED_NFIT BIT_ULL(3)
137137
#define MCE_HANDLED_EDAC BIT_ULL(4)
138138
#define MCE_HANDLED_MCELOG BIT_ULL(5)
139+
140+
/*
141+
* Indicates an MCE which has happened in kernel space but from
142+
* which the kernel can recover simply by executing fixup_exception()
143+
* so that an error is returned to the caller of the function that
144+
* hit the machine check.
145+
*/
139146
#define MCE_IN_KERNEL_RECOV BIT_ULL(6)
140147

148+
/*
149+
* Indicates an MCE that happened in kernel space while copying data
150+
* from user. In this case fixup_exception() gets the kernel to the
151+
* error exit for the copy function. Machine check handler can then
152+
* treat it like a fault taken in user mode.
153+
*/
154+
#define MCE_IN_KERNEL_COPYIN BIT_ULL(7)
155+
141156
/*
142157
* This structure contains all data related to the MCE log. Also
143158
* carries a signature to make it easier to find from external

arch/x86/lib/copy_user_64.S

Lines changed: 48 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@
3636
jmp .Lcopy_user_handle_tail
3737
.previous
3838

39-
_ASM_EXTABLE_UA(100b, 103b)
40-
_ASM_EXTABLE_UA(101b, 103b)
39+
_ASM_EXTABLE_CPY(100b, 103b)
40+
_ASM_EXTABLE_CPY(101b, 103b)
4141
.endm
4242

4343
/*
@@ -116,26 +116,26 @@ SYM_FUNC_START(copy_user_generic_unrolled)
116116
60: jmp .Lcopy_user_handle_tail /* ecx is zerorest also */
117117
.previous
118118

119-
_ASM_EXTABLE_UA(1b, 30b)
120-
_ASM_EXTABLE_UA(2b, 30b)
121-
_ASM_EXTABLE_UA(3b, 30b)
122-
_ASM_EXTABLE_UA(4b, 30b)
123-
_ASM_EXTABLE_UA(5b, 30b)
124-
_ASM_EXTABLE_UA(6b, 30b)
125-
_ASM_EXTABLE_UA(7b, 30b)
126-
_ASM_EXTABLE_UA(8b, 30b)
127-
_ASM_EXTABLE_UA(9b, 30b)
128-
_ASM_EXTABLE_UA(10b, 30b)
129-
_ASM_EXTABLE_UA(11b, 30b)
130-
_ASM_EXTABLE_UA(12b, 30b)
131-
_ASM_EXTABLE_UA(13b, 30b)
132-
_ASM_EXTABLE_UA(14b, 30b)
133-
_ASM_EXTABLE_UA(15b, 30b)
134-
_ASM_EXTABLE_UA(16b, 30b)
135-
_ASM_EXTABLE_UA(18b, 40b)
136-
_ASM_EXTABLE_UA(19b, 40b)
137-
_ASM_EXTABLE_UA(21b, 50b)
138-
_ASM_EXTABLE_UA(22b, 50b)
119+
_ASM_EXTABLE_CPY(1b, 30b)
120+
_ASM_EXTABLE_CPY(2b, 30b)
121+
_ASM_EXTABLE_CPY(3b, 30b)
122+
_ASM_EXTABLE_CPY(4b, 30b)
123+
_ASM_EXTABLE_CPY(5b, 30b)
124+
_ASM_EXTABLE_CPY(6b, 30b)
125+
_ASM_EXTABLE_CPY(7b, 30b)
126+
_ASM_EXTABLE_CPY(8b, 30b)
127+
_ASM_EXTABLE_CPY(9b, 30b)
128+
_ASM_EXTABLE_CPY(10b, 30b)
129+
_ASM_EXTABLE_CPY(11b, 30b)
130+
_ASM_EXTABLE_CPY(12b, 30b)
131+
_ASM_EXTABLE_CPY(13b, 30b)
132+
_ASM_EXTABLE_CPY(14b, 30b)
133+
_ASM_EXTABLE_CPY(15b, 30b)
134+
_ASM_EXTABLE_CPY(16b, 30b)
135+
_ASM_EXTABLE_CPY(18b, 40b)
136+
_ASM_EXTABLE_CPY(19b, 40b)
137+
_ASM_EXTABLE_CPY(21b, 50b)
138+
_ASM_EXTABLE_CPY(22b, 50b)
139139
SYM_FUNC_END(copy_user_generic_unrolled)
140140
EXPORT_SYMBOL(copy_user_generic_unrolled)
141141

@@ -180,8 +180,8 @@ SYM_FUNC_START(copy_user_generic_string)
180180
jmp .Lcopy_user_handle_tail
181181
.previous
182182

183-
_ASM_EXTABLE_UA(1b, 11b)
184-
_ASM_EXTABLE_UA(3b, 12b)
183+
_ASM_EXTABLE_CPY(1b, 11b)
184+
_ASM_EXTABLE_CPY(3b, 12b)
185185
SYM_FUNC_END(copy_user_generic_string)
186186
EXPORT_SYMBOL(copy_user_generic_string)
187187

@@ -213,7 +213,7 @@ SYM_FUNC_START(copy_user_enhanced_fast_string)
213213
jmp .Lcopy_user_handle_tail
214214
.previous
215215

216-
_ASM_EXTABLE_UA(1b, 12b)
216+
_ASM_EXTABLE_CPY(1b, 12b)
217217
SYM_FUNC_END(copy_user_enhanced_fast_string)
218218
EXPORT_SYMBOL(copy_user_enhanced_fast_string)
219219

@@ -237,7 +237,7 @@ SYM_CODE_START_LOCAL(.Lcopy_user_handle_tail)
237237
ASM_CLAC
238238
ret
239239

240-
_ASM_EXTABLE_UA(1b, 2b)
240+
_ASM_EXTABLE_CPY(1b, 2b)
241241
SYM_CODE_END(.Lcopy_user_handle_tail)
242242

243243
/*
@@ -366,27 +366,27 @@ SYM_FUNC_START(__copy_user_nocache)
366366
jmp .Lcopy_user_handle_tail
367367
.previous
368368

369-
_ASM_EXTABLE_UA(1b, .L_fixup_4x8b_copy)
370-
_ASM_EXTABLE_UA(2b, .L_fixup_4x8b_copy)
371-
_ASM_EXTABLE_UA(3b, .L_fixup_4x8b_copy)
372-
_ASM_EXTABLE_UA(4b, .L_fixup_4x8b_copy)
373-
_ASM_EXTABLE_UA(5b, .L_fixup_4x8b_copy)
374-
_ASM_EXTABLE_UA(6b, .L_fixup_4x8b_copy)
375-
_ASM_EXTABLE_UA(7b, .L_fixup_4x8b_copy)
376-
_ASM_EXTABLE_UA(8b, .L_fixup_4x8b_copy)
377-
_ASM_EXTABLE_UA(9b, .L_fixup_4x8b_copy)
378-
_ASM_EXTABLE_UA(10b, .L_fixup_4x8b_copy)
379-
_ASM_EXTABLE_UA(11b, .L_fixup_4x8b_copy)
380-
_ASM_EXTABLE_UA(12b, .L_fixup_4x8b_copy)
381-
_ASM_EXTABLE_UA(13b, .L_fixup_4x8b_copy)
382-
_ASM_EXTABLE_UA(14b, .L_fixup_4x8b_copy)
383-
_ASM_EXTABLE_UA(15b, .L_fixup_4x8b_copy)
384-
_ASM_EXTABLE_UA(16b, .L_fixup_4x8b_copy)
385-
_ASM_EXTABLE_UA(20b, .L_fixup_8b_copy)
386-
_ASM_EXTABLE_UA(21b, .L_fixup_8b_copy)
387-
_ASM_EXTABLE_UA(30b, .L_fixup_4b_copy)
388-
_ASM_EXTABLE_UA(31b, .L_fixup_4b_copy)
389-
_ASM_EXTABLE_UA(40b, .L_fixup_1b_copy)
390-
_ASM_EXTABLE_UA(41b, .L_fixup_1b_copy)
369+
_ASM_EXTABLE_CPY(1b, .L_fixup_4x8b_copy)
370+
_ASM_EXTABLE_CPY(2b, .L_fixup_4x8b_copy)
371+
_ASM_EXTABLE_CPY(3b, .L_fixup_4x8b_copy)
372+
_ASM_EXTABLE_CPY(4b, .L_fixup_4x8b_copy)
373+
_ASM_EXTABLE_CPY(5b, .L_fixup_4x8b_copy)
374+
_ASM_EXTABLE_CPY(6b, .L_fixup_4x8b_copy)
375+
_ASM_EXTABLE_CPY(7b, .L_fixup_4x8b_copy)
376+
_ASM_EXTABLE_CPY(8b, .L_fixup_4x8b_copy)
377+
_ASM_EXTABLE_CPY(9b, .L_fixup_4x8b_copy)
378+
_ASM_EXTABLE_CPY(10b, .L_fixup_4x8b_copy)
379+
_ASM_EXTABLE_CPY(11b, .L_fixup_4x8b_copy)
380+
_ASM_EXTABLE_CPY(12b, .L_fixup_4x8b_copy)
381+
_ASM_EXTABLE_CPY(13b, .L_fixup_4x8b_copy)
382+
_ASM_EXTABLE_CPY(14b, .L_fixup_4x8b_copy)
383+
_ASM_EXTABLE_CPY(15b, .L_fixup_4x8b_copy)
384+
_ASM_EXTABLE_CPY(16b, .L_fixup_4x8b_copy)
385+
_ASM_EXTABLE_CPY(20b, .L_fixup_8b_copy)
386+
_ASM_EXTABLE_CPY(21b, .L_fixup_8b_copy)
387+
_ASM_EXTABLE_CPY(30b, .L_fixup_4b_copy)
388+
_ASM_EXTABLE_CPY(31b, .L_fixup_4b_copy)
389+
_ASM_EXTABLE_CPY(40b, .L_fixup_1b_copy)
390+
_ASM_EXTABLE_CPY(41b, .L_fixup_1b_copy)
391391
SYM_FUNC_END(__copy_user_nocache)
392392
EXPORT_SYMBOL(__copy_user_nocache)

arch/x86/mm/extable.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,18 @@ __visible bool ex_handler_uaccess(const struct exception_table_entry *fixup,
8080
}
8181
EXPORT_SYMBOL(ex_handler_uaccess);
8282

83+
__visible bool ex_handler_copy(const struct exception_table_entry *fixup,
84+
struct pt_regs *regs, int trapnr,
85+
unsigned long error_code,
86+
unsigned long fault_addr)
87+
{
88+
WARN_ONCE(trapnr == X86_TRAP_GP, "General protection fault in user access. Non-canonical address?");
89+
regs->ip = ex_fixup_addr(fixup);
90+
regs->ax = trapnr;
91+
return true;
92+
}
93+
EXPORT_SYMBOL(ex_handler_copy);
94+
8395
__visible bool ex_handler_rdmsr_unsafe(const struct exception_table_entry *fixup,
8496
struct pt_regs *regs, int trapnr,
8597
unsigned long error_code,
@@ -136,7 +148,7 @@ enum handler_type ex_get_fault_handler_type(unsigned long ip)
136148
handler = ex_fixup_handler(e);
137149
if (handler == ex_handler_fault)
138150
return EX_HANDLER_FAULT;
139-
else if (handler == ex_handler_uaccess)
151+
else if (handler == ex_handler_uaccess || handler == ex_handler_copy)
140152
return EX_HANDLER_UACCESS;
141153
else
142154
return EX_HANDLER_OTHER;

0 commit comments

Comments
 (0)