Module Name:    src
Committed By:   pooka
Date:           Mon Feb 21 20:23:29 UTC 2011

Modified Files:
        src/sys/kern: kern_exec.c kern_exit.c kern_lwp.c
        src/sys/sys: lwp.h

Log Message:
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


To generate a diff of this commit:
cvs rdiff -u -r1.307 -r1.308 src/sys/kern/kern_exec.c
cvs rdiff -u -r1.231 -r1.232 src/sys/kern/kern_exit.c
cvs rdiff -u -r1.155 -r1.156 src/sys/kern/kern_lwp.c
cvs rdiff -u -r1.148 -r1.149 src/sys/sys/lwp.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/kern/kern_exec.c
diff -u src/sys/kern/kern_exec.c:1.307 src/sys/kern/kern_exec.c:1.308
--- src/sys/kern/kern_exec.c:1.307	Tue Feb 15 16:49:54 2011
+++ src/sys/kern/kern_exec.c	Mon Feb 21 20:23:29 2011
@@ -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);

Index: src/sys/kern/kern_exit.c
diff -u src/sys/kern/kern_exit.c:1.231 src/sys/kern/kern_exit.c:1.232
--- src/sys/kern/kern_exit.c:1.231	Sat Dec 18 01:36:19 2010
+++ src/sys/kern/kern_exit.c	Mon Feb 21 20:23:28 2011
@@ -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);
 	}

Index: src/sys/kern/kern_lwp.c
diff -u src/sys/kern/kern_lwp.c:1.155 src/sys/kern/kern_lwp.c:1.156
--- src/sys/kern/kern_lwp.c:1.155	Thu Feb 17 18:50:02 2011
+++ src/sys/kern/kern_lwp.c	Mon Feb 21 20:23:28 2011
@@ -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;

Index: src/sys/sys/lwp.h
diff -u src/sys/sys/lwp.h:1.148 src/sys/sys/lwp.h:1.149
--- src/sys/sys/lwp.h:1.148	Sat Feb 19 20:19:54 2011
+++ src/sys/sys/lwp.h	Mon Feb 21 20:23:28 2011
@@ -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.

Reply via email to