Source-Changes-HG archive

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

[src/trunk]: src/sys/kern Fix a longstanding problem with LWP limits. When c...



details:   https://anonhg.NetBSD.org/src/rev/92977150fde8
branches:  trunk
changeset: 846782:92977150fde8
user:      ad <ad%NetBSD.org@localhost>
date:      Sun Dec 01 15:27:58 2019 +0000

description:
Fix a longstanding problem with LWP limits.  When changing the user's
LWP count, we must use the process credentials because that's what
the accounting entity is tied to.

Reported-by: syzbot+d193266676f635661c62%syzkaller.appspotmail.com@localhost

diffstat:

 sys/kern/kern_lwp.c |  41 ++++++++++++++++++++---------------------
 1 files changed, 20 insertions(+), 21 deletions(-)

diffs (89 lines):

diff -r 753b5e5c6d28 -r 92977150fde8 sys/kern/kern_lwp.c
--- a/sys/kern/kern_lwp.c       Sun Dec 01 15:07:04 2019 +0000
+++ b/sys/kern/kern_lwp.c       Sun Dec 01 15:27:58 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_lwp.c,v 1.214 2019/11/24 13:23:57 ad Exp $        */
+/*     $NetBSD: kern_lwp.c,v 1.215 2019/12/01 15:27:58 ad Exp $        */
 
 /*-
  * Copyright (c) 2001, 2006, 2007, 2008, 2009, 2019 The NetBSD Foundation, Inc.
@@ -209,7 +209,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.214 2019/11/24 13:23:57 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.215 2019/12/01 15:27:58 ad Exp $");
 
 #include "opt_ddb.h"
 #include "opt_lockdebug.h"
@@ -771,17 +771,21 @@
     lwp_t **rnewlwpp, int sclass, const sigset_t *sigmask,
     const stack_t *sigstk)
 {
-       struct lwp *l2, *isfree;
+       struct lwp *l2;
        turnstile_t *ts;
        lwpid_t lid;
 
        KASSERT(l1 == curlwp || l1->l_proc == &proc0);
 
        /*
-        * Enforce limits, excluding the first lwp and kthreads.
+        * Enforce limits, excluding the first lwp and kthreads.  We must
+        * use the process credentials here when adjusting the limit, as
+        * they are what's tied to the accounting entity.  However for
+        * authorizing the action, we'll use the LWP's credentials.
         */
+       mutex_enter(p2->p_lock);
        if (p2->p_nlwps != 0 && p2 != &proc0) {
-               uid_t uid = kauth_cred_getuid(l1->l_cred);
+               uid_t uid = kauth_cred_getuid(p2->p_cred);
                int count = chglwpcnt(uid, 1);
                if (__predict_false(count >
                    p2->p_rlimit[RLIMIT_NTHR].rlim_cur)) {
@@ -791,6 +795,7 @@
                            &p2->p_rlimit[RLIMIT_NTHR], KAUTH_ARG(RLIMIT_NTHR))
                            != 0) {
                                (void)chglwpcnt(uid, -1);
+                               mutex_exit(p2->p_lock);
                                return EAGAIN;
                        }
                }
@@ -800,27 +805,21 @@
         * First off, reap any detached LWP waiting to be collected.
         * We can re-use its LWP structure and turnstile.
         */
-       isfree = NULL;
-       if (p2->p_zomblwp != NULL) {
-               mutex_enter(p2->p_lock);
-               if ((isfree = p2->p_zomblwp) != NULL) {
-                       p2->p_zomblwp = NULL;
-                       lwp_free(isfree, true, false);/* releases proc mutex */
-               } else
-                       mutex_exit(p2->p_lock);
-       }
-       if (isfree == NULL) {
-               l2 = pool_cache_get(lwp_cache, PR_WAITOK);
-               memset(l2, 0, sizeof(*l2));
-               l2->l_ts = pool_cache_get(turnstile_cache, PR_WAITOK);
-               SLIST_INIT(&l2->l_pi_lenders);
-       } else {
-               l2 = isfree;
+       if ((l2 = p2->p_zomblwp) != NULL) {
+               p2->p_zomblwp = NULL;
+               lwp_free(l2, true, false);
+               /* p2 now unlocked by lwp_free() */
                ts = l2->l_ts;
                KASSERT(l2->l_inheritedprio == -1);
                KASSERT(SLIST_EMPTY(&l2->l_pi_lenders));
                memset(l2, 0, sizeof(*l2));
                l2->l_ts = ts;
+       } else {
+               mutex_exit(p2->p_lock);
+               l2 = pool_cache_get(lwp_cache, PR_WAITOK);
+               memset(l2, 0, sizeof(*l2));
+               l2->l_ts = pool_cache_get(turnstile_cache, PR_WAITOK);
+               SLIST_INIT(&l2->l_pi_lenders);
        }
 
        l2->l_stat = LSIDL;



Home | Main Index | Thread Index | Old Index