Date: Fri, 16 Oct 2015 20:51:25 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> 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 Message-ID: <201510162051.t9GKpPG6071607@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201510162051.t9GKpPG6071607>