summaryrefslogtreecommitdiffstats
path: root/sys/amd64/amd64/cpu_switch.S
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2008-09-02 17:52:11 +0000
committerkib <kib@FreeBSD.org>2008-09-02 17:52:11 +0000
commit59a00054acff9e2ada7d2366d4aeaec829dcd3a4 (patch)
tree6ebcf1585c96d0e1d8f54111b10eb1820d727ffe /sys/amd64/amd64/cpu_switch.S
parent84967086499f3a1a3480390747da9dcc1ae26abd (diff)
downloadFreeBSD-src-59a00054acff9e2ada7d2366d4aeaec829dcd3a4.zip
FreeBSD-src-59a00054acff9e2ada7d2366d4aeaec829dcd3a4.tar.gz
- When executing FreeBSD/amd64 binaries from FreeBSD/i386 or Linux/i386
processes, clear PCB_32BIT and PCB_GS32BIT bits [1]. - Reread the fs and gs bases from the msr unconditionally, not believing the values in pcb_fsbase and pcb_gsbase, since usermode may reload segment registers, invalidating the cache. [2]. Both problems resulted in the wrong fs base, causing wrong tls pointer be dereferenced in the usermode. Reported and tested by: Vyacheslav Bocharov <adeepv at gmail com> [1] Reported by: Bernd Walter <ticsoat cicely7 cicely de>, Artem Belevich <fbsdlist at src cx>[2] Reviewed by: peter MFC after: 3 days
Diffstat (limited to 'sys/amd64/amd64/cpu_switch.S')
-rw-r--r--sys/amd64/amd64/cpu_switch.S20
1 files changed, 18 insertions, 2 deletions
diff --git a/sys/amd64/amd64/cpu_switch.S b/sys/amd64/amd64/cpu_switch.S
index f34b0cc..a0b11f8 100644
--- a/sys/amd64/amd64/cpu_switch.S
+++ b/sys/amd64/amd64/cpu_switch.S
@@ -109,8 +109,24 @@ ENTRY(cpu_switch)
movq %rsp,PCB_RSP(%r8)
movq %rbx,PCB_RBX(%r8)
movq %rax,PCB_RIP(%r8)
- movq PCB_FSBASE(%r8),%r9
- movq PCB_GSBASE(%r8),%r10
+
+ /*
+ * Reread fs and gs bases. Explicit fs segment register load
+ * by the usermode code may change actual fs base without
+ * updating pcb_{fs,gs}base.
+ *
+ * %rdx still contains the mtx, save %rdx around rdmsr.
+ */
+ movq %rdx,%r11
+ movl $MSR_FSBASE,%ecx
+ rdmsr
+ shlq $32,%rdx
+ leaq (%rax,%rdx),%r9
+ movl $MSR_KGSBASE,%ecx
+ rdmsr
+ shlq $32,%rdx
+ leaq (%rax,%rdx),%r10
+ movq %r11,%rdx
testl $PCB_32BIT,PCB_FLAGS(%r8)
jnz store_seg
OpenPOWER on IntegriCloud