From owner-svn-src-stable-10@freebsd.org Fri Oct 16 20:51:26 2015 Return-Path: Delivered-To: svn-src-stable-10@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id D0187A17F5E; Fri, 16 Oct 2015 20:51:26 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 8DFF51BD9; Fri, 16 Oct 2015 20:51:26 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id t9GKpPZm071609; Fri, 16 Oct 2015 20:51:25 GMT (envelope-from kib@FreeBSD.org) Received: (from kib@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id t9GKpPG6071607; Fri, 16 Oct 2015 20:51:25 GMT (envelope-from kib@FreeBSD.org) Message-Id: <201510162051.t9GKpPG6071607@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kib set sender to kib@FreeBSD.org using -f From: Konstantin Belousov Date: Fri, 16 Oct 2015 20:51:25 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r289431 - stable/10/sys/kern X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-10@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 16 Oct 2015 20:51:26 -0000 Author: kib Date: Fri Oct 16 20:51:25 2015 New Revision: 289431 URL: https://svnweb.freebsd.org/changeset/base/289431 Log: MFC r289026: Enforce the maxproc limitation before allocating struct proc. In collaboration with: pho Modified: stable/10/sys/kern/kern_exit.c stable/10/sys/kern/kern_fork.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/kern/kern_exit.c ============================================================================== --- stable/10/sys/kern/kern_exit.c Fri Oct 16 20:23:04 2015 (r289430) +++ stable/10/sys/kern/kern_exit.c Fri Oct 16 20:51:25 2015 (r289431) @@ -957,9 +957,7 @@ proc_reap(struct thread *td, struct proc KASSERT(FIRST_THREAD_IN_PROC(p), ("proc_reap: no residual thread!")); uma_zfree(proc_zone, p); - sx_xlock(&allproc_lock); - nprocs--; - sx_xunlock(&allproc_lock); + atomic_add_int(&nprocs, -1); } static int Modified: stable/10/sys/kern/kern_fork.c ============================================================================== --- stable/10/sys/kern/kern_fork.c Fri Oct 16 20:23:04 2015 (r289430) +++ stable/10/sys/kern/kern_fork.c Fri Oct 16 20:51:25 2015 (r289431) @@ -386,12 +386,6 @@ do_fork(struct thread *td, int flags, st p2_held = 0; p1 = td->td_proc; - /* - * Increment the nprocs resource before blocking can occur. There - * are hard-limits as to the number of processes that can run. - */ - nprocs++; - trypid = fork_findpid(flags); sx_sunlock(&proctree_lock); @@ -773,18 +767,16 @@ int fork1(struct thread *td, int flags, int pages, struct proc **procp, int *procdescp, int pdflags) { - struct proc *p1; - struct proc *newproc; - int ok; + struct proc *p1, *newproc; struct thread *td2; struct vmspace *vm2; +#ifdef PROCDESC + struct file *fp_procdesc; +#endif vm_ooffset_t mem_charged; - int error; + int error, nprocs_new, ok; static int curfail; static struct timeval lastfail; -#ifdef PROCDESC - struct file *fp_procdesc = NULL; -#endif /* Check for the undefined or unimplemented flags. */ if ((flags & ~(RFFLAGS | RFTSIGFLAGS(RFTSIGMASK))) != 0) @@ -826,6 +818,37 @@ fork1(struct thread *td, int flags, int } #ifdef PROCDESC + fp_procdesc = NULL; +#endif + newproc = NULL; + vm2 = NULL; + + /* + * Increment the nprocs resource before allocations occur. + * Although process entries are dynamically created, we still + * keep a global limit on the maximum number we will + * create. There are hard-limits as to the number of processes + * that can run, established by the KVA and memory usage for + * the process data. + * + * Don't allow a nonprivileged user to use the last ten + * processes; don't let root exceed the limit. + */ + nprocs_new = atomic_fetchadd_int(&nprocs, 1) + 1; + if ((nprocs_new >= maxproc - 10 && priv_check_cred(td->td_ucred, + PRIV_MAXPROC, 0) != 0) || nprocs_new >= maxproc) { + sx_xlock(&allproc_lock); + if (ppsratecheck(&lastfail, &curfail, 1)) { + printf("maxproc limit exceeded by uid %u (pid %d); " + "see tuning(7) and login.conf(5)\n", + td->td_ucred->cr_ruid, p1->p_pid); + } + sx_xunlock(&allproc_lock); + error = EAGAIN; + goto fail1; + } + +#ifdef PROCDESC /* * If required, create a process descriptor in the parent first; we * will abandon it if something goes wrong. We don't finit() until @@ -834,12 +857,11 @@ fork1(struct thread *td, int flags, int if (flags & RFPROCDESC) { error = falloc(td, &fp_procdesc, procdescp, 0); if (error != 0) - return (error); + goto fail1; } #endif mem_charged = 0; - vm2 = NULL; if (pages == 0) pages = KSTACK_PAGES; /* Allocate new proc. */ @@ -906,20 +928,7 @@ fork1(struct thread *td, int flags, int /* We have to lock the process tree while we look for a pid. */ sx_slock(&proctree_lock); - - /* - * Although process entries are dynamically created, we still keep - * a global limit on the maximum number we will create. Don't allow - * a nonprivileged user to use the last ten processes; don't let root - * exceed the limit. The variable nprocs is the current number of - * processes, maxproc is the limit. - */ sx_xlock(&allproc_lock); - if ((nprocs >= maxproc - 10 && priv_check_cred(td->td_ucred, - PRIV_MAXPROC, 0) != 0) || nprocs >= maxproc) { - error = EAGAIN; - goto fail; - } /* * Increment the count of procs running with this uid. Don't allow @@ -954,11 +963,7 @@ fork1(struct thread *td, int flags, int } error = EAGAIN; -fail: sx_sunlock(&proctree_lock); - if (ppsratecheck(&lastfail, &curfail, 1)) - printf("maxproc limit exceeded by uid %u (pid %d); see tuning(7) and login.conf(5)\n", - td->td_ucred->cr_ruid, p1->p_pid); sx_xunlock(&allproc_lock); #ifdef MAC mac_proc_destroy(newproc); @@ -974,6 +979,7 @@ fail1: fdrop(fp_procdesc, td); } #endif + atomic_add_int(&nprocs, -1); pause("fork", hz / 2); return (error); }