From 78d58cb6bc1ea3b5c1028aa2a57ac43228ef29d6 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 5 Oct 2017 12:50:03 +0000 Subject: [PATCH] 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 --- sys/amd64/amd64/sys_machdep.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sys/amd64/amd64/sys_machdep.c b/sys/amd64/amd64/sys_machdep.c index 9a7de13bdcf1..079c3732e858 100644 --- a/sys/amd64/amd64/sys_machdep.c +++ b/sys/amd64/amd64/sys_machdep.c @@ -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); }