git: c7e5802ab6e6 - main - amd64: do not restore fsbase/gsbase for 32bit processes
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 21 Jun 2026 12:17:41 UTC
The branch main has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=c7e5802ab6e6230a5782a09c914585d055eb5223
commit c7e5802ab6e6230a5782a09c914585d055eb5223
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-06-16 21:44:00 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2026-06-21 12:17:11 +0000
amd64: do not restore fsbase/gsbase for 32bit processes
There is no WRFSBASE and WRGSBASE 32bit variants at all. As such, the
fsbase and gsbase must always be equal to the bases in the corresponding
segment descriptor, same as on real i386.
If a 32bit program reloads either %fs or %gs using setcontext(9) or
sigreturn(9), restoring bases from the syscall entry time is wrong.
In all other cases, hardware already does the right action when the
segment register is loaded, and the bases for the ufssel/ugssel in GDT
are updated on the context switch.
Reviewed by: markj (previous version)
Tested by: terehovv@mail.ru
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Differential revision: https://reviews.freebsd.org/D57611
---
sys/amd64/amd64/exception.S | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/sys/amd64/amd64/exception.S b/sys/amd64/amd64/exception.S
index 5ff75fb65740..4d58e07caf4b 100644
--- a/sys/amd64/amd64/exception.S
+++ b/sys/amd64/amd64/exception.S
@@ -1161,12 +1161,15 @@ do_segs:
.globl ld_fs
ld_fs:
movw %ax,%fs
+ testl $PCB_32BIT,PCB_FLAGS(%r8)
+ jnz after_ld_fsbase
movl $MSR_FSBASE,%ecx
movl PCB_FSBASE(%r8),%eax
movl PCB_FSBASE+4(%r8),%edx
.globl ld_fsbase
ld_fsbase:
wrmsr
+after_ld_fsbase:
/* Restore %gs and gsbase */
movw TF_GS(%rsp),%si
pushfq
@@ -1179,6 +1182,8 @@ ld_fsbase:
.globl ld_gs
ld_gs:
movw %si,%gs
+ testl $PCB_32BIT,PCB_FLAGS(%r8)
+ jnz ld_gsbase_32
/* Restore kernel %gs base */
movl %r12d,%eax
movl %r13d,%edx
@@ -1194,6 +1199,8 @@ ld_gs:
.globl ld_gsbase
ld_gsbase:
wrmsr /* May trap if non-canonical, but only for TLS. */
+
+after_ld_gsbase:
.globl ld_es
ld_es:
movw TF_ES(%rsp),%es
@@ -1241,6 +1248,30 @@ ld_regs:
doreti_iret:
iretq
+ /*
+ * 32bit gsbase path.
+ * The KGSBASE is not loaded from the pcb_gsbase, instead we move
+ * the GSBASE value into KGSBASE right after loading user %gs, then
+ * restore kernel gsbase.
+ */
+ld_gsbase_32:
+ /* Read the user gsbase into %r14d:%r15d. */
+ movl $MSR_GSBASE,%ecx
+ rdmsr
+ movl %eax,%r14d
+ movl %edx,%r15d
+ /* Restore kernel %gs base */
+ movl %r12d,%eax
+ movl %r13d,%edx
+ wrmsr
+ popfq
+ /* Load the user gsbase into KGSBASE. */
+ movl $MSR_KGSBASE,%ecx
+ movl %r14d,%eax
+ movl %r15d,%edx
+ wrmsr
+ jmp after_ld_gsbase
+
set_segs:
movw $KUDSEL,%ax
movw %ax,TF_DS(%rsp)