Avoid a race betweem freeing LDT and context switches.

cpu_switch.S uses curproc->p_md.md_ldt value as the flag indicating
presence of the process LDT.  The flag is checked and then ldt segment
descriptor is copied into the CPU' GDT slot.

Disallow context switches around clearing of the curproc LDT state by
performing the cleanup in critical section.  Ensure that the md_ldt
flag is cleared before md_ldt_sd descriptor content is destroyed by
inserting fence between the operations.

We depend on the x86 memory model strong ordering guarantees, in
particular, that cpu_switch.S observes the writes to md_ldt and
md_ldt_sd in the expected order.

Discussed with:	bde
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
This commit is contained in:
Konstantin Belousov 2017-10-05 12:50:03 +00:00
parent 31f976bc4a
commit 78d58cb6bc
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=324313

View File

@ -514,10 +514,13 @@ user_ldt_free(struct thread *td)
return;
}
critical_enter();
mdp->md_ldt = NULL;
atomic_thread_fence_rel();
bzero(&mdp->md_ldt_sd, sizeof(mdp->md_ldt_sd));
if (td == curthread)
lldt(GSEL(GNULL_SEL, SEL_KPL));
critical_exit();
user_ldt_deref(pldt);
}