--- sys/kern/kern_fork.c.orig 2004-09-12 15:55:22.000000000 -0300 +++ sys/kern/kern_fork.c 2004-09-12 16:11:46.000000000 -0300 @@ -272,6 +272,19 @@ return (EAGAIN); } + /* Check if this user has reached his fork depth limit */ + if (p1->p_rlimit[RLIMIT_FORK].rlim_cur == 0) { + /* + * Back out the process count + */ + nprocs--; + if (ppsratecheck(&lastfail, &curfail, 1)) + printf("maximum fork depth exceeded by uid %d, please " + "see login.conf(5).\n", uid); + tsleep(&forksleep, 0, "fork", hz / 2); + return(EPERM); + } + /* Allocate new proc. */ newproc = zalloc(proc_zone); @@ -451,13 +464,24 @@ p2->p_fdtol = fdtol; /* - * If p_limit is still copy-on-write, bump refcnt, - * otherwise get a copy that won't be modified. + * If p_limit is still copy-on-write, and the fork + * depth was not limited, bump refcnt, otherwise + * get a copy that won't be modified and update the + * fork depth limits. * (If PL_SHAREMOD is clear, the structure is shared * copy-on-write.) */ - if (p1->p_limit->p_lflags & PL_SHAREMOD) { + if (p1->p_limit->p_lflags & PL_SHAREMOD || + p1->p_rlimit[RLIMIT_FORK].rlim_cur != RLIM_INFINITY) { p2->p_limit = limcopy(p1->p_limit); + if (p1->p_rlimit[RLIMIT_FORK].rlim_cur != RLIM_INFINITY) { + p2->p_rlimit[RLIMIT_FORK].rlim_cur = + p1->p_rlimit[RLIMIT_FORK].rlim_cur - 1; + } + if (p1->p_rlimit[RLIMIT_FORK].rlim_max != RLIM_INFINITY) { + p2->p_rlimit[RLIMIT_FORK].rlim_max = + p1->p_rlimit[RLIMIT_FORK].rlim_max - 1; + } } else { p2->p_limit = p1->p_limit; p2->p_limit->p_refcnt++;