]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/commit
amd64: Only update fsbase/gsbase in pcb for curthread.
authorJohn Baldwin <jhb@FreeBSD.org>
Fri, 12 Mar 2021 17:45:18 +0000 (09:45 -0800)
committerJohn Baldwin <jhb@FreeBSD.org>
Mon, 29 Mar 2021 18:09:26 +0000 (11:09 -0700)
commit57d7992b50ba36290422bd208d45033de8946307
tree06d7c81ab2a116ce4780c5192d632d635dad6cbd
parent16443ffd4108bed3c290fee90d7337ba6877bb3e
amd64: Only update fsbase/gsbase in pcb for curthread.

Before the pcb is copied to the new thread during cpu_fork() and
cpu_copy_thread(), the kernel re-reads the current register values in
case they are stale.  This is done by setting PCB_FULL_IRET in
pcb_flags.

This works fine for user threads, but the creation of kernel processes
and kernel threads do not follow the normal synchronization rules for
pcb_flags.  Specifically, new kernel processes are always forked from
thread0, not from curthread, so adjusting pcb_flags via a simple
instruction without the LOCK prefix can race with thread0 running on
another CPU.  Similarly, kthread_add() clones from the first thread in
the relevant kernel process, not from curthread.  In practice, Netflix
encountered a panic where the pcb_flags in the first kthread of the
KTLS process were trashed due to update_pcb_bases() in
cpu_copy_thread() running from thread0 to create one of the other KTLS
threads racing with the first KTLS kthread calling fpu_kern_thread()
on another CPU.  In the panicking case, the write to update pcb_flags
in fpu_kern_thread() was lost triggering an "Unregistered use of FPU
in kernel" panic when the first KTLS kthread later tried to use the
FPU.

Sponsored by: Netflix

(cherry picked from commit 92211458689b448cda52a659f9d192fef5a9dd50)
sys/amd64/amd64/vm_machdep.c