HomeFreeBSD

amd64: Only update fsbase/gsbase in pcb for curthread.

Description

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)

Details

Provenance
jhbAuthored on Mar 12 2021, 5:45 PM
Parents
rG16443ffd4108: bsdinstall: Drop vestigial bsdinstall-esps cleanup
Branches
Unknown
Tags
Unknown