Hi

I made some tests and almost all Linux distros brings down while freebsd survive!Forkbombing is a big problem but i don't think that something like

max_threads = mempages / (16 * THREAD_SIZE / PAGE_SIZE);

is good solution!!!
How about add max_user_threads to the kernel? It could be tunable via proc filesystem. Limit is set only for users.
I made a fast:) patch - see below - and test it on 2.6.11, 2.6.11ac4,2.6.12rc1...works great!!!New forks are stoped in copy_process() before dup_task_struct() and EAGAIN is returned. System works without any problems and root can killall -9 forkbomb.


Regards,
        Jacek Luczak
--- linux-2.6.12-rc1/kernel/fork.c      2005-03-29 00:53:37.000000000 +0200
+++ linux/kernel/fork.c 2005-03-29 00:54:19.000000000 +0200
@@ -57,6 +57,8 @@
 
 int max_threads;               /* tunable limit on nr_threads */
 
+int max_user_threads;          /* tunable limit on nr_threads per user */
+
 DEFINE_PER_CPU(unsigned long, process_counts) = 0;
 
  __cacheline_aligned DEFINE_RWLOCK(tasklist_lock);  /* outer */
@@ -146,6 +148,21 @@
        if(max_threads < 20)
                max_threads = 20;
 
+       /*
+        * The default maximum number of threads per user.
+        * 
+        * FIXME: this value is based on my experiments and is 
+        * rather good on desktop system; it should be fixed to
+        * the more universal value.
+        */
+       max_user_threads = 300;
+       
+       /*
+        * default value is too high - set to max_threads 
+        */
+       if (max_threads < max_user_threads)
+               max_user_threads = max_threads;
+       
        init_task.signal->rlim[RLIMIT_NPROC].rlim_cur = max_threads/2;
        init_task.signal->rlim[RLIMIT_NPROC].rlim_max = max_threads/2;
        init_task.signal->rlim[RLIMIT_SIGPENDING] =
@@ -179,6 +196,16 @@
        return tsk;
 }
 
+/*
+ * This is used to get number of user processes
+ * from current running task.
+ */
+static inline int get_user_processes(void)
+{
+       return atomic_read(&current->user->processes);
+}
+#define user_nr_processes get_user_processes()
+
 #ifdef CONFIG_MMU
 static inline int dup_mmap(struct mm_struct * mm, struct mm_struct * oldmm)
 {
@@ -869,6 +896,13 @@
                goto fork_out;
 
        retval = -ENOMEM;
+       
+       /*
+        * Stop creation of new user process if limit is reached.
+        */
+       if ( (current->user != &root_user) && (user_nr_processes >= 
max_user_threads) )
+               goto max_user_fork;
+       
        p = dup_task_struct(current);
        if (!p)
                goto fork_out;
@@ -1109,6 +1143,9 @@
                return ERR_PTR(retval);
        return p;
 
+max_user_fork:
+       retval = -EAGAIN;
+       return ERR_PTR(retval);
 bad_fork_cleanup_namespace:
        exit_namespace(p);
 bad_fork_cleanup_keys:
--- linux-2.6.12-rc1/kernel/sysctl.c    2005-03-29 00:53:38.000000000 +0200
+++ linux/kernel/sysctl.c       2005-03-29 00:54:19.000000000 +0200
@@ -56,6 +56,7 @@
 extern int sysctl_overcommit_memory;
 extern int sysctl_overcommit_ratio;
 extern int max_threads;
+extern int max_user_threads;
 extern int sysrq_enabled;
 extern int core_uses_pid;
 extern char core_pattern[];
@@ -642,6 +643,14 @@
                .mode           = 0644,
                .proc_handler   = &proc_dointvec,
        },
+       {
+               .ctl_name       = KERN_MAX_USER_THREADS,
+               .procname       = "user_threads_max",
+               .data           = &max_user_threads,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec,
+       },
 
        { .ctl_name = 0 }
 };
--- linux-2.6.12-rc1/include/linux/sysctl.h     2005-03-29 00:54:06.000000000 
+0200
+++ linux/include/linux/sysctl.h        2005-03-29 00:54:36.000000000 +0200
@@ -136,6 +136,7 @@
        KERN_UNKNOWN_NMI_PANIC=66, /* int: unknown nmi panic flag */
        KERN_BOOTLOADER_TYPE=67, /* int: boot loader type */
        KERN_RANDOMIZE=68, /* int: randomize virtual address space */
+       KERN_MAX_USER_THREADS=69,       /* int: Maximum nr of threads per user 
in the system */
 };
 
 
begin:vcard
fn;quoted-printable:Jacek =C5=81uczak
n;quoted-printable:=C5=81uczak;Jacek
adr:;;Prof. Z. Szafrana 4a;Zielona Gora;;65-516;Poland
email;internet:[EMAIL PROTECTED]
title:Linux Registered User # 337142
x-mozilla-html:FALSE
url:http://pin.if.uz.zgora.pl/~difrost
version:2.1
end:vcard

Reply via email to