Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/kern Fix crash observed with procfs on current-users by ...



details:   https://anonhg.NetBSD.org/src/rev/77c644c639ca
branches:  trunk
changeset: 1008564:77c644c639ca
user:      ad <ad%NetBSD.org@localhost>
date:      Thu Mar 26 21:31:55 2020 +0000

description:
Fix crash observed with procfs on current-users by David Hopper.  LWP refcnt
and p_zomblwp both must reach the needed state, and LSZOMB be set, under a
single hold of p_lock.

diffstat:

 sys/kern/kern_exit.c |   8 +++++---
 sys/kern/kern_lwp.c  |  40 +++++++++++++++++++++++-----------------
 2 files changed, 28 insertions(+), 20 deletions(-)

diffs (130 lines):

diff -r 7d7cc8d16aa3 -r 77c644c639ca sys/kern/kern_exit.c
--- a/sys/kern/kern_exit.c      Thu Mar 26 21:25:26 2020 +0000
+++ b/sys/kern/kern_exit.c      Thu Mar 26 21:31:55 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_exit.c,v 1.285 2020/03/08 15:05:18 ad Exp $       */
+/*     $NetBSD: kern_exit.c,v 1.286 2020/03/26 21:31:55 ad Exp $       */
 
 /*-
  * Copyright (c) 1998, 1999, 2006, 2007, 2008, 2020 The NetBSD Foundation, Inc.
@@ -67,7 +67,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_exit.c,v 1.285 2020/03/08 15:05:18 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_exit.c,v 1.286 2020/03/26 21:31:55 ad Exp $");
 
 #include "opt_ktrace.h"
 #include "opt_dtrace.h"
@@ -559,7 +559,9 @@
        /* Free the linux lwp id */
        if ((l->l_pflag & LP_PIDLID) != 0 && l->l_lid != p->p_pid)
                proc_free_pid(l->l_lid);
-       lwp_drainrefs(l);
+       if (l->l_refcnt > 0) {
+               lwp_drainrefs(l);
+       }
        lwp_lock(l);
        l->l_prflag &= ~LPR_DETACHED;
        l->l_stat = LSZOMB;
diff -r 7d7cc8d16aa3 -r 77c644c639ca sys/kern/kern_lwp.c
--- a/sys/kern/kern_lwp.c       Thu Mar 26 21:25:26 2020 +0000
+++ b/sys/kern/kern_lwp.c       Thu Mar 26 21:31:55 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_lwp.c,v 1.230 2020/03/26 20:19:06 ad Exp $        */
+/*     $NetBSD: kern_lwp.c,v 1.231 2020/03/26 21:31:55 ad Exp $        */
 
 /*-
  * Copyright (c) 2001, 2006, 2007, 2008, 2009, 2019, 2020
@@ -211,7 +211,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.230 2020/03/26 20:19:06 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.231 2020/03/26 21:31:55 ad Exp $");
 
 #include "opt_ddb.h"
 #include "opt_lockdebug.h"
@@ -274,7 +274,7 @@
        .l_stat = LSONPROC,
        .l_ts = &turnstile0,
        .l_syncobj = &sched_syncobj,
-       .l_refcnt = 1,
+       .l_refcnt = 0,
        .l_priority = PRI_USER + NPRI_USER - 1,
        .l_inheritedprio = -1,
        .l_class = SCHED_OTHER,
@@ -821,7 +821,7 @@
 
        l2->l_stat = LSIDL;
        l2->l_proc = p2;
-       l2->l_refcnt = 1;
+       l2->l_refcnt = 0;
        l2->l_class = sclass;
 
        /*
@@ -1180,19 +1180,27 @@
         * mark it waiting for collection in the proc structure.  Note that
         * before we can do that, we need to free any other dead, deatched
         * LWP waiting to meet its maker.
+        *
+        * All conditions need to be observed upon under the same hold of
+        * p_lock, because if the lock is dropped any of them can change.
         */
        mutex_enter(p->p_lock);
-       lwp_drainrefs(l);
-
-       if ((l->l_prflag & LPR_DETACHED) != 0) {
-               while ((l2 = p->p_zomblwp) != NULL) {
-                       p->p_zomblwp = NULL;
-                       lwp_free(l2, false, false);/* releases proc mutex */
-                       mutex_enter(p->p_lock);
-                       l->l_refcnt++;
+       for (;;) {
+               if (l->l_refcnt > 0) {
                        lwp_drainrefs(l);
+                       continue;
                }
-               p->p_zomblwp = l;
+               if ((l->l_prflag & LPR_DETACHED) != 0) {
+                       if ((l2 = p->p_zomblwp) != NULL) {
+                               p->p_zomblwp = NULL;
+                               lwp_free(l2, false, false);
+                               /* proc now unlocked */
+                               mutex_enter(p->p_lock);
+                               continue;
+                       }
+                       p->p_zomblwp = l;
+               }
+               break;
        }
 
        /*
@@ -1692,7 +1700,6 @@
 
        KASSERT(mutex_owned(l->l_proc->p_lock));
        KASSERT(l->l_stat != LSZOMB);
-       KASSERT(l->l_refcnt != 0);
 
        l->l_refcnt++;
 }
@@ -1724,6 +1731,7 @@
        KASSERT(mutex_owned(p->p_lock));
        KASSERT(l->l_stat != LSZOMB);
        KASSERT(l->l_refcnt > 0);
+
        if (--l->l_refcnt == 0)
                cv_broadcast(&p->p_lwpcv);
 }
@@ -1737,10 +1745,8 @@
        struct proc *p = l->l_proc;
 
        KASSERT(mutex_owned(p->p_lock));
-       KASSERT(l->l_refcnt != 0);
 
-       l->l_refcnt--;
-       while (l->l_refcnt != 0)
+       while (l->l_refcnt > 0)
                cv_wait(&p->p_lwpcv, p->p_lock);
 }
 



Home | Main Index | Thread Index | Old Index