summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2010-01-09 11:28:01 +0000
committerkib <kib@FreeBSD.org>2010-01-09 11:28:01 +0000
commit057178fcfdf664738bc92dac90a8f413c377bc20 (patch)
tree4e60e66a65650433bddad3bfc988072d0d04f280
parent4113919b07e278ff6076716d6bdc5f973da25ef5 (diff)
downloadFreeBSD-src-057178fcfdf664738bc92dac90a8f413c377bc20.zip
FreeBSD-src-057178fcfdf664738bc92dac90a8f413c377bc20.tar.gz
Set md_ldt (pointer to the LDT) after md_ldt_sd (system segment
descriptor for the LDT) is populated. md_ldt is used by context-switch code as indicator that LDT segment register shall be loaded with GUSERLDT segment instead of 0, so context switch at the wrong time may cause attempt to load non-populated descriptor. Use store with the barrier to prevent other CPUs from seeing updated md_ldt but not seeing updated md_ldt_sd. Multithreaded process may context-switch to another thread of the process on another CPU and read md_ldt. MFC after: 1 week
-rw-r--r--sys/amd64/amd64/sys_machdep.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/sys/amd64/amd64/sys_machdep.c b/sys/amd64/amd64/sys_machdep.c
index 1cba8a2..bb81664 100644
--- a/sys/amd64/amd64/sys_machdep.c
+++ b/sys/amd64/amd64/sys_machdep.c
@@ -420,13 +420,14 @@ user_ldt_alloc(struct proc *p, int force)
return (pldt);
}
- mdp->md_ldt = new_ldt;
if (pldt != NULL) {
bcopy(pldt->ldt_base, new_ldt->ldt_base, max_ldt_segment *
sizeof(struct user_segment_descriptor));
user_ldt_derefl(pldt);
}
ssdtosyssd(&sldt, &p->p_md.md_ldt_sd);
+ atomic_store_rel_ptr((volatile uintptr_t *)&mdp->md_ldt,
+ (uintptr_t)new_ldt);
if (p == curproc)
set_user_ldt(mdp);
OpenPOWER on IntegriCloud