Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys Borrow the lwpctl data area from the parent for the vfor...
details: https://anonhg.NetBSD.org/src/rev/8063f7b2b15f
branches: trunk
changeset: 762484:8063f7b2b15f
user: pooka <pooka%NetBSD.org@localhost>
date: Mon Feb 21 20:23:28 2011 +0000
description:
Borrow the lwpctl data area from the parent for the vfork() child.
Otherwise the child will incorrectly see it is not running on any
CPU. Among other things, this fixes crashes from having
LD_PRELOAD=libpthread.so set in the env.
reviewed by tech-kern
diffstat:
sys/kern/kern_exec.c | 5 +++--
sys/kern/kern_exit.c | 5 +++--
sys/kern/kern_lwp.c | 36 +++++++++++++++++++++++++++++++++---
sys/sys/lwp.h | 5 +++--
4 files changed, 42 insertions(+), 9 deletions(-)
diffs (160 lines):
diff -r 5731eaa4d56c -r 8063f7b2b15f sys/kern/kern_exec.c
--- a/sys/kern/kern_exec.c Mon Feb 21 20:11:56 2011 +0000
+++ b/sys/kern/kern_exec.c Mon Feb 21 20:23:28 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_exec.c,v 1.307 2011/02/15 16:49:54 pooka Exp $ */
+/* $NetBSD: kern_exec.c,v 1.308 2011/02/21 20:23:29 pooka Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -59,7 +59,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.307 2011/02/15 16:49:54 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.308 2011/02/21 20:23:29 pooka Exp $");
#include "opt_ktrace.h"
#include "opt_modular.h"
@@ -978,6 +978,7 @@
*/
if ((p->p_lflag & PL_PPWAIT) != 0) {
mutex_enter(proc_lock);
+ l->l_lwpctl = NULL; /* was on loan from blocked parent */
p->p_lflag &= ~PL_PPWAIT;
cv_broadcast(&p->p_pptr->p_waitcv);
mutex_exit(proc_lock);
diff -r 5731eaa4d56c -r 8063f7b2b15f sys/kern/kern_exit.c
--- a/sys/kern/kern_exit.c Mon Feb 21 20:11:56 2011 +0000
+++ b/sys/kern/kern_exit.c Mon Feb 21 20:23:28 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_exit.c,v 1.231 2010/12/18 01:36:19 rmind Exp $ */
+/* $NetBSD: kern_exit.c,v 1.232 2011/02/21 20:23:28 pooka Exp $ */
/*-
* Copyright (c) 1998, 1999, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -67,7 +67,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_exit.c,v 1.231 2010/12/18 01:36:19 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_exit.c,v 1.232 2011/02/21 20:23:28 pooka Exp $");
#include "opt_ktrace.h"
#include "opt_perfctrs.h"
@@ -341,6 +341,7 @@
*/
mutex_enter(proc_lock);
if (p->p_lflag & PL_PPWAIT) {
+ l->l_lwpctl = NULL; /* was on loan from blocked parent */
p->p_lflag &= ~PL_PPWAIT;
cv_broadcast(&p->p_pptr->p_waitcv);
}
diff -r 5731eaa4d56c -r 8063f7b2b15f sys/kern/kern_lwp.c
--- a/sys/kern/kern_lwp.c Mon Feb 21 20:11:56 2011 +0000
+++ b/sys/kern/kern_lwp.c Mon Feb 21 20:23:28 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_lwp.c,v 1.155 2011/02/17 18:50:02 matt Exp $ */
+/* $NetBSD: kern_lwp.c,v 1.156 2011/02/21 20:23:28 pooka Exp $ */
/*-
* Copyright (c) 2001, 2006, 2007, 2008, 2009 The NetBSD Foundation, Inc.
@@ -211,7 +211,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.155 2011/02/17 18:50:02 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.156 2011/02/21 20:23:28 pooka Exp $");
#include "opt_ddb.h"
#include "opt_lockdebug.h"
@@ -697,6 +697,15 @@
TAILQ_INIT(&l2->l_ld_locks);
/*
+ * For vfork, borrow parent's lwpctl context if it exists.
+ * This also causes us to return via lwp_userret.
+ */
+ if (flags & LWP_VFORK && l1->l_lwpctl) {
+ l2->l_lwpctl = l1->l_lwpctl;
+ l2->l_flag |= LW_LWPCTL;
+ }
+
+ /*
* If not the first LWP in the process, grab a reference to the
* descriptor table.
*/
@@ -1377,6 +1386,16 @@
KASSERT(0);
/* NOTREACHED */
}
+
+ /* update lwpctl processor (for vfork child_return) */
+ if (l->l_flag & LW_LWPCTL) {
+ lwp_lock(l);
+ KASSERT(kpreempt_disabled());
+ l->l_lwpctl->lc_curcpu = (int)cpu_index(l->l_cpu);
+ l->l_lwpctl->lc_pctr++;
+ l->l_flag &= ~LW_LWPCTL;
+ lwp_unlock(l);
+ }
}
#ifdef KERN_SA
@@ -1530,6 +1549,10 @@
l = curlwp;
p = l->l_proc;
+ /* don't allow a vforked process to create lwp ctls */
+ if (p->p_lflag & PL_PPWAIT)
+ return EBUSY;
+
if (l->l_lcpage != NULL) {
lcp = l->l_lcpage;
*uaddr = lcp->lcp_uaddr + (vaddr_t)l->l_lwpctl - lcp->lcp_kaddr;
@@ -1654,11 +1677,18 @@
void
lwp_ctl_free(lwp_t *l)
{
+ struct proc *p = l->l_proc;
lcproc_t *lp;
lcpage_t *lcp;
u_int map, offset;
- lp = l->l_proc->p_lwpctl;
+ /* don't free a lwp context we borrowed for vfork */
+ if (p->p_lflag & PL_PPWAIT) {
+ l->l_lwpctl = NULL;
+ return;
+ }
+
+ lp = p->p_lwpctl;
KASSERT(lp != NULL);
lcp = l->l_lcpage;
diff -r 5731eaa4d56c -r 8063f7b2b15f sys/sys/lwp.h
--- a/sys/sys/lwp.h Mon Feb 21 20:11:56 2011 +0000
+++ b/sys/sys/lwp.h Mon Feb 21 20:23:28 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: lwp.h,v 1.148 2011/02/19 20:19:54 matt Exp $ */
+/* $NetBSD: lwp.h,v 1.149 2011/02/21 20:23:28 pooka Exp $ */
/*-
* Copyright (c) 2001, 2006, 2007, 2008, 2009, 2010
@@ -215,6 +215,7 @@
/* These flags are kept in l_flag. */
#define LW_IDLE 0x00000001 /* Idle lwp. */
+#define LW_LWPCTL 0x00000002 /* Adjust lwpctl in userret */
#define LW_SINTR 0x00000080 /* Sleep is interruptible. */
#define LW_SA_SWITCHING 0x00000100 /* SA LWP in context switch */
#define LW_SYSTEM 0x00000200 /* Kernel thread */
@@ -259,7 +260,7 @@
* user.
*/
#define LW_USERRET (LW_WEXIT|LW_PENDSIG|LW_WREBOOT|LW_WSUSPEND|LW_WCORE|\
- LW_SA_BLOCKING|LW_SA_UPCALL)
+ LW_SA_BLOCKING|LW_SA_UPCALL|LW_LWPCTL)
/*
* Status values.
Home |
Main Index |
Thread Index |
Old Index