diff options
author | Jan Beulich <JBeulich@novell.com> | 2009-09-30 06:22:11 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-10-01 05:24:26 -0400 |
commit | 24e35800cdc4350fc34e2bed37b608a9e13ab3b6 (patch) | |
tree | 0e592a3f097d101263c7da4fc529f86d03cf9f2a /arch/x86/ia32/ia32entry.S | |
parent | 4701472e441e41be2549a25228f703bc9cd13b5b (diff) |
x86: Don't leak 64-bit kernel register values to 32-bit processes
While 32-bit processes can't directly access R8...R15, they can
gain access to these registers by temporarily switching themselves
into 64-bit mode.
Therefore, registers not preserved anyway by called C functions
(i.e. R8...R11) must be cleared prior to returning to user mode.
Signed-off-by: Jan Beulich <jbeulich@novell.com>
Cc: <stable@kernel.org>
LKML-Reference: <4AC34D73020000780001744A@vpn.id2.novell.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/ia32/ia32entry.S')
-rw-r--r-- | arch/x86/ia32/ia32entry.S | 36 |
1 files changed, 23 insertions, 13 deletions
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index 74619c4f9fda..1733f9f65e82 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S | |||
@@ -21,8 +21,8 @@ | |||
21 | #define __AUDIT_ARCH_LE 0x40000000 | 21 | #define __AUDIT_ARCH_LE 0x40000000 |
22 | 22 | ||
23 | #ifndef CONFIG_AUDITSYSCALL | 23 | #ifndef CONFIG_AUDITSYSCALL |
24 | #define sysexit_audit int_ret_from_sys_call | 24 | #define sysexit_audit ia32_ret_from_sys_call |
25 | #define sysretl_audit int_ret_from_sys_call | 25 | #define sysretl_audit ia32_ret_from_sys_call |
26 | #endif | 26 | #endif |
27 | 27 | ||
28 | #define IA32_NR_syscalls ((ia32_syscall_end - ia32_sys_call_table)/8) | 28 | #define IA32_NR_syscalls ((ia32_syscall_end - ia32_sys_call_table)/8) |
@@ -39,12 +39,12 @@ | |||
39 | .endm | 39 | .endm |
40 | 40 | ||
41 | /* clobbers %eax */ | 41 | /* clobbers %eax */ |
42 | .macro CLEAR_RREGS _r9=rax | 42 | .macro CLEAR_RREGS offset=0, _r9=rax |
43 | xorl %eax,%eax | 43 | xorl %eax,%eax |
44 | movq %rax,R11(%rsp) | 44 | movq %rax,\offset+R11(%rsp) |
45 | movq %rax,R10(%rsp) | 45 | movq %rax,\offset+R10(%rsp) |
46 | movq %\_r9,R9(%rsp) | 46 | movq %\_r9,\offset+R9(%rsp) |
47 | movq %rax,R8(%rsp) | 47 | movq %rax,\offset+R8(%rsp) |
48 | .endm | 48 | .endm |
49 | 49 | ||
50 | /* | 50 | /* |
@@ -172,6 +172,10 @@ sysexit_from_sys_call: | |||
172 | movl RIP-R11(%rsp),%edx /* User %eip */ | 172 | movl RIP-R11(%rsp),%edx /* User %eip */ |
173 | CFI_REGISTER rip,rdx | 173 | CFI_REGISTER rip,rdx |
174 | RESTORE_ARGS 1,24,1,1,1,1 | 174 | RESTORE_ARGS 1,24,1,1,1,1 |
175 | xorq %r8,%r8 | ||
176 | xorq %r9,%r9 | ||
177 | xorq %r10,%r10 | ||
178 | xorq %r11,%r11 | ||
175 | popfq | 179 | popfq |
176 | CFI_ADJUST_CFA_OFFSET -8 | 180 | CFI_ADJUST_CFA_OFFSET -8 |
177 | /*CFI_RESTORE rflags*/ | 181 | /*CFI_RESTORE rflags*/ |
@@ -202,7 +206,7 @@ sysexit_from_sys_call: | |||
202 | 206 | ||
203 | .macro auditsys_exit exit,ebpsave=RBP | 207 | .macro auditsys_exit exit,ebpsave=RBP |
204 | testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),TI_flags(%r10) | 208 | testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),TI_flags(%r10) |
205 | jnz int_ret_from_sys_call | 209 | jnz ia32_ret_from_sys_call |
206 | TRACE_IRQS_ON | 210 | TRACE_IRQS_ON |
207 | sti | 211 | sti |
208 | movl %eax,%esi /* second arg, syscall return value */ | 212 | movl %eax,%esi /* second arg, syscall return value */ |
@@ -218,8 +222,9 @@ sysexit_from_sys_call: | |||
218 | cli | 222 | cli |
219 | TRACE_IRQS_OFF | 223 | TRACE_IRQS_OFF |
220 | testl %edi,TI_flags(%r10) | 224 | testl %edi,TI_flags(%r10) |
221 | jnz int_with_check | 225 | jz \exit |
222 | jmp \exit | 226 | CLEAR_RREGS -ARGOFFSET |
227 | jmp int_with_check | ||
223 | .endm | 228 | .endm |
224 | 229 | ||
225 | sysenter_auditsys: | 230 | sysenter_auditsys: |
@@ -329,6 +334,9 @@ sysretl_from_sys_call: | |||
329 | CFI_REGISTER rip,rcx | 334 | CFI_REGISTER rip,rcx |
330 | movl EFLAGS-ARGOFFSET(%rsp),%r11d | 335 | movl EFLAGS-ARGOFFSET(%rsp),%r11d |
331 | /*CFI_REGISTER rflags,r11*/ | 336 | /*CFI_REGISTER rflags,r11*/ |
337 | xorq %r10,%r10 | ||
338 | xorq %r9,%r9 | ||
339 | xorq %r8,%r8 | ||
332 | TRACE_IRQS_ON | 340 | TRACE_IRQS_ON |
333 | movl RSP-ARGOFFSET(%rsp),%esp | 341 | movl RSP-ARGOFFSET(%rsp),%esp |
334 | CFI_RESTORE rsp | 342 | CFI_RESTORE rsp |
@@ -353,7 +361,7 @@ cstar_tracesys: | |||
353 | #endif | 361 | #endif |
354 | xchgl %r9d,%ebp | 362 | xchgl %r9d,%ebp |
355 | SAVE_REST | 363 | SAVE_REST |
356 | CLEAR_RREGS r9 | 364 | CLEAR_RREGS 0, r9 |
357 | movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */ | 365 | movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */ |
358 | movq %rsp,%rdi /* &pt_regs -> arg1 */ | 366 | movq %rsp,%rdi /* &pt_regs -> arg1 */ |
359 | call syscall_trace_enter | 367 | call syscall_trace_enter |
@@ -425,6 +433,8 @@ ia32_do_call: | |||
425 | call *ia32_sys_call_table(,%rax,8) # xxx: rip relative | 433 | call *ia32_sys_call_table(,%rax,8) # xxx: rip relative |
426 | ia32_sysret: | 434 | ia32_sysret: |
427 | movq %rax,RAX-ARGOFFSET(%rsp) | 435 | movq %rax,RAX-ARGOFFSET(%rsp) |
436 | ia32_ret_from_sys_call: | ||
437 | CLEAR_RREGS -ARGOFFSET | ||
428 | jmp int_ret_from_sys_call | 438 | jmp int_ret_from_sys_call |
429 | 439 | ||
430 | ia32_tracesys: | 440 | ia32_tracesys: |
@@ -442,8 +452,8 @@ END(ia32_syscall) | |||
442 | 452 | ||
443 | ia32_badsys: | 453 | ia32_badsys: |
444 | movq $0,ORIG_RAX-ARGOFFSET(%rsp) | 454 | movq $0,ORIG_RAX-ARGOFFSET(%rsp) |
445 | movq $-ENOSYS,RAX-ARGOFFSET(%rsp) | 455 | movq $-ENOSYS,%rax |
446 | jmp int_ret_from_sys_call | 456 | jmp ia32_sysret |
447 | 457 | ||
448 | quiet_ni_syscall: | 458 | quiet_ni_syscall: |
449 | movq $-ENOSYS,%rax | 459 | movq $-ENOSYS,%rax |