Add a special-case handler for general protection faults. It appears to
be possible to get the swapgs state reversed if doreti traps during the iretq. Attempt to handle this. load_gs() might need special handling too. Running the kernel with the user's TLS and the kernel's PCPU space interchanged would be bad(TM). Discovered as a result of a conversation with: bde Approved by: re
This commit is contained in:
parent
2de92a386e
commit
2bdfd0d814
@ -126,8 +126,6 @@ IDTVEC(missing)
|
|||||||
TRAP_ERR(T_SEGNPFLT)
|
TRAP_ERR(T_SEGNPFLT)
|
||||||
IDTVEC(stk)
|
IDTVEC(stk)
|
||||||
TRAP_ERR(T_STKFLT)
|
TRAP_ERR(T_STKFLT)
|
||||||
IDTVEC(prot)
|
|
||||||
TRAP_ERR(T_PROTFLT)
|
|
||||||
IDTVEC(align)
|
IDTVEC(align)
|
||||||
TRAP_ERR(T_ALIGNFLT)
|
TRAP_ERR(T_ALIGNFLT)
|
||||||
|
|
||||||
@ -203,7 +201,8 @@ IDTVEC(page)
|
|||||||
testb $SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
|
testb $SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
|
||||||
jz 1f /* already running with kernel GS.base */
|
jz 1f /* already running with kernel GS.base */
|
||||||
swapgs
|
swapgs
|
||||||
1: movq %rdi,TF_RDI(%rsp) /* free up a GP register */
|
1:
|
||||||
|
movq %rdi,TF_RDI(%rsp) /* free up a GP register */
|
||||||
movq %cr2,%rdi /* preserve %cr2 before .. */
|
movq %cr2,%rdi /* preserve %cr2 before .. */
|
||||||
movq %rdi,TF_ADDR(%rsp) /* enabling interrupts. */
|
movq %rdi,TF_ADDR(%rsp) /* enabling interrupts. */
|
||||||
testl $PSL_I,TF_RFLAGS(%rsp)
|
testl $PSL_I,TF_RFLAGS(%rsp)
|
||||||
@ -211,6 +210,30 @@ IDTVEC(page)
|
|||||||
sti
|
sti
|
||||||
jmp alltraps_pushregs_no_rdi
|
jmp alltraps_pushregs_no_rdi
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We have to special-case this one. If we get a trap in doreti() at
|
||||||
|
* the iretq stage, we'll reenter with the wrong gs state. We'll have
|
||||||
|
* to do a special the swapgs in this case even coming from the kernel.
|
||||||
|
* XXX linux has a trap handler for their equivalent of load_gs().
|
||||||
|
*/
|
||||||
|
IDTVEC(prot)
|
||||||
|
subq $TF_ERR,%rsp
|
||||||
|
movq $T_PROTFLT,TF_TRAPNO(%rsp)
|
||||||
|
movq $0,TF_ADDR(%rsp)
|
||||||
|
movq %rdi,TF_RDI(%rsp) /* free up a GP register */
|
||||||
|
leaq doreti_iret(%rip),%rdi
|
||||||
|
cmpq %rdi,TF_RIP(%rsp)
|
||||||
|
je 2f /* kernel but with user gsbase!! */
|
||||||
|
testb $SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
|
||||||
|
jz 1f /* already running with kernel GS.base */
|
||||||
|
2:
|
||||||
|
swapgs
|
||||||
|
1:
|
||||||
|
testl $PSL_I,TF_RFLAGS(%rsp)
|
||||||
|
jz alltraps_pushregs_no_rdi
|
||||||
|
sti
|
||||||
|
jmp alltraps_pushregs_no_rdi
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fast syscall entry point. We enter here with just our new %cs/%ss set,
|
* Fast syscall entry point. We enter here with just our new %cs/%ss set,
|
||||||
* and the new privilige level. We are still running on the old user stack
|
* and the new privilige level. We are still running on the old user stack
|
||||||
|
Loading…
Reference in New Issue
Block a user