amd64: only set PCB_FULL_IRET pcb flag when #gp or similar exception comes

from usermode.

If CPU supports RDFSBASE, the flag also means that userspace fsbase
and gsbase are already written into pcb, which might be not true when
we handle #gp from kernel.

The offender is rdmsr_safe(), and the visible result is corrupted
userspace TLS base.

Reported by:	pstef
Sponsored by:	The FreeBSD Foundation
MFC after:	3 days
This commit is contained in:
kib 2019-11-13 22:39:46 +00:00
parent 54a2495b27
commit 2d220d40d8

View File

@ -497,8 +497,8 @@ prot_addrf:
3: cmpw $KUG32SEL,TF_GS(%rsp)
jne 4f
movq %rdx,PCB_GSBASE(%rdi)
orl $PCB_FULL_IRET,PCB_FLAGS(%rdi) /* full iret from user #gp */
4: call handle_ibrs_entry
orl $PCB_FULL_IRET,PCB_FLAGS(%rdi) /* always full iret from GPF */
movw %es,TF_ES(%rsp)
movw %ds,TF_DS(%rsp)
testl $PSL_I,TF_RFLAGS(%rsp)