Subject: Fork bomb protection patch
To: None <tech-kern@netbsd.org>
From: Jaromir Dolecek <jdolecek@netbsd.org>
List: tech-kern
Date: 12/04/2002 10:07:35
Hi,
following is a deal with common forkbomb attacks. The change
is based on FreeBSD kern_fork.c change in rev.1.132. Please
let me know if you'd see anything obviously wrong in the
patch; I'll commit the change later today otherwise.

Changes:
* leave 10 processes for root-only use
  - 1 is not enough to get through sshd login nowadays (as pointed
    out by Bang Jun-Young), and it makes it easier for root
    to handle the problem
* use ratecheck() to limit the 'table full' messages to once per 10s 
  - this is to reduce spam to syslogd and thus log/console; this
    is still useful even through syslogd normally doesn't actually
    log the repeated messages
* make process sleep for 0.5s if the system table is full
  or when the user reaches their process number limit
  - this is to not hog the system with huge number of CPU-hungry
    looping processes

Jaromir

Index: kern_fork.c
===================================================================
RCS file: /cvsroot/syssrc/sys/kern/kern_fork.c,v
retrieving revision 1.100
diff -u -p -r1.100 kern_fork.c
--- kern_fork.c	2002/11/30 11:20:51	1.100
+++ kern_fork.c	2002/12/04 08:46:02
@@ -189,6 +189,9 @@ sys___clone(struct proc *p, void *v, reg
 	    NULL, NULL, retval, NULL));
 }
 
+/* print the 'table full' message once per 10 seconds */
+struct timeval fork_tfmrate = { 10, 0 };
+
 int
 fork1(struct proc *p1, int flags, int exitsig, void *stack, size_t stacksize,
     void (*func)(void *), void *arg, register_t *retval,
@@ -209,9 +212,13 @@ fork1(struct proc *p1, int flags, int ex
 	 * processes, maxproc is the limit.
 	 */
 	uid = p1->p_cred->p_ruid;
-	if (__predict_false((nprocs >= maxproc - 1 && uid != 0) ||
+	if (__predict_false((nprocs >= maxproc - 10 && uid != 0) ||
 			    nprocs >= maxproc)) {
-		tablefull("proc", "increase kern.maxproc or NPROC");
+		static struct timeval lasttfm;
+
+		if (ratecheck(&lasttfm, &fork_tfmrate))
+			tablefull("proc", "increase kern.maxproc or NPROC");
+		(void)tsleep(&nprocs, PUSER, "forkmx", hz / 2);
 		return (EAGAIN);
 	}
 	nprocs++;
@@ -225,6 +232,7 @@ fork1(struct proc *p1, int flags, int ex
 			    p1->p_rlimit[RLIMIT_NPROC].rlim_cur)) {
 		(void)chgproccnt(uid, -1);
 		nprocs--;
+		(void)tsleep(&nprocs, PUSER, "forkulim", hz / 2);
 		return (EAGAIN);
 	}
 
-- 
Jaromir Dolecek <jdolecek@NetBSD.org>            http://www.NetBSD.org/
-=- We should be mindful of the potential goal, but as the tantric    -=-
-=- Buddhist masters say, ``You may notice during meditation that you -=-
-=- sometimes levitate or glow.   Do not let this distract you.''     -=-