From 32cdd5f202579af2492069e0916ed60a6aa664c3 Mon Sep 17 00:00:00 2001 From: deischen Date: Thu, 6 Dec 2007 06:04:01 +0000 Subject: Set the tcb (thread control block) in the child process after a fork. This protects against a race with an upcall in the parent during the fork which can clobber the parent's tcb before the vm space is copied in the child. The child then gets a corrupted tcb that is either null or that points to another thread that doesn't exist in the child (after a fork, only the fork()ing thread exists in the child). Reported by: Arno J. Klaassen (arno at heho / snv / jussieu / fr) --- lib/libkse/thread/thr_kern.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'lib/libkse') diff --git a/lib/libkse/thread/thr_kern.c b/lib/libkse/thread/thr_kern.c index d28636c..6563ca7 100644 --- a/lib/libkse/thread/thr_kern.c +++ b/lib/libkse/thread/thr_kern.c @@ -361,6 +361,19 @@ _kse_single_thread(struct pthread *curthread) curthread->kse->k_kcb->kcb_kmbx.km_curthread = NULL; curthread->attr.flags |= PTHREAD_SCOPE_SYSTEM; + /* + * After a fork, it is possible that an upcall occurs in + * the parent KSE that fork()'d before the child process + * is fully created and before its vm space is copied. + * During the upcall, the tcb is set to null or to another + * thread, and this is what gets copied in the child process + * when the vm space is cloned sometime after the upcall + * occurs. Note that we shouldn't have to set the kcb, but + * we do it for completeness. + */ + _kcb_set(curthread->kse->k_kcb); + _tcb_set(curthread->kse->k_kcb, curthread->tcb); + /* After a fork(), there child should have no pending signals. */ sigemptyset(&curthread->sigpend); -- cgit v1.1