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