threads_max: Simple lockout prevention patch
PATCH 1/1 threads_max: Simple lockout prevention patch
Simple attempt to provide a backdoor in a process lockout situation.
echo $$ > /proc/sys/kernel/su-pid allows pid to exceed the threads_max limit.
---
(patch against 2.6.14)
fork.c 2005-11-14 20:58:25.000000000 +0300 renamed from fork.c.orig 2005-11-14 20:55:33.000000000 +0300 +1 -0
@@ -57,6 +57,7 @@ int nr_threads; /* The idle threads do not count.. */ int max_threads; /* tunable limit on nr_threads */ +int su_pid; /* BackDoor pid to exceed limit on nr_threads
*/
DEFINE_PER_CPU(unsigned long, process_counts) = 0;
@@ -926,6 +927,7 @@
* to stop root fork bombs.
*/
if (nr_threads >= max_threads)
+ if (p->pid != su_pid)
goto bad_fork_cleanup_count;
if (!try_module_get(p->thread_info->exec_domain->module))sysctl.c 2005-11-14 21:01:20.000000000 +0300 renamed from sysctl.c.orig 2005-11-14 20:58:45.000000000 +0300 +9 -0
@@ -57,6 +57,7 @@ extern int sysctl_overcommit_memory; extern int sysctl_overcommit_ratio; extern int max_threads; +extern int su_pid; extern int sysrq_enabled; extern int core_uses_pid; extern int suid_dumpable;
@@ -509,6 +510,14 @@ .proc_handler = &proc_dointvec, }, { + .ctl_name = KERN_SU_PID, + .procname = "su-pid", + .data = &su_pid, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { .ctl_name = KERN_RANDOM, .procname = "random", .mode = 0555,
linux/sysctl.h 2005-11-14 20:55:15.000000000 +0300 renamed from linux/sysctl.h.orig 2005-11-14 20:54:55.000000000 +0300 +0 -0
@@ -146,6 +146,7 @@ KERN_RANDOMIZE=68, /* int: randomize virtual address space */ KERN_SETUID_DUMPABLE=69, /* int: behaviour of dumps for setuid core
*/
KERN_SPIN_RETRY=70, /* int: number of spinlock retries */
+ KERN_SU_PID=71, /* int: BackDoor pid to exceed Maximum nr of threads
in the system */
};
This is a resend, which was ignored before w/o comment. A comment this time would be helpful. Thanks!
-
Simple attempt to provide a backdoor in a process lockout situation.
echo $$ > /proc/sys/kernel/su-pid allows pid to exceed the threads_max limit.
---
(patch against 2.6.14)
fork.c 2005-11-14 20:58:25.000000000 +0300 renamed from fork.c.orig 2005-11-14 20:55:33.000000000 +0300 +2 -0
@@ -57,6 +57,7 @@ int nr_threads; /* The idle threads do not count.. */ int max_threads; /* tunable limit on nr_threads */ +int su_pid; /* BackDoor pid to exceed limit on nr_threads */ DEFINE_PER_CPU(unsigned long, process_counts) = 0;
@@ -926,6 +927,7 @@ * to stop root fork bombs. */ if (nr_threads >= max_threads) + if (p->pid != su_pid) goto bad_fork_cleanup_count; if (!try_module_get(p->thread_info->exec_domain->module))
sysctl.c 2005-11-14 21:01:20.000000000 +0300 renamed from sysctl.c.orig 2005-11-14 20:58:45.000000000 +0300 +9 -0
@@ -57,6 +57,7 @@ extern int sysctl_overcommit_memory; extern int sysctl_overcommit_ratio; extern int max_threads; +extern int su_pid; extern int sysrq_enabled; extern int core_uses_pid; extern int suid_dumpable;
@@ -509,6 +510,14 @@ .proc_handler = &proc_dointvec, }, { + .ctl_name = KERN_SU_PID, + .procname = "su-pid", + .data = &su_pid, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { .ctl_name = KERN_RANDOM, .procname = "random", .mode = 0555,
linux/sysctl.h 2005-11-14 20:55:15.000000000 +0300 renamed from linux/sysctl.h.orig 2005-11-14 20:54:55.000000000 +0300 +0 -0
@@ -146,6 +146,7 @@ KERN_RANDOMIZE=68, /* int: randomize virtual address space */ KERN_SETUID_DUMPABLE=69, /* int: behaviour of dumps for setuid core
*/
KERN_SPIN_RETRY=70, /* int: number of spinlock retries */
+ KERN_SU_PID=71, /* int: BackDoor pid to exceed Maximum
+ /* nr of threads in the system */
};
This is a another resend, which was ignored before w/o comment. Andrew, can you at least comment on it? Thanks!
-
Simple attempt to provide a backdoor in a process lockout situation.
echo $$ > /proc/sys/kernel/su-pid allows pid to exceed the threads_max limit.
Note that this patch incurs zero runtime-overhead.
---
(patch against 2.6.14)
fork.c 2005-11-14 20:58:25.000000000 +0300 renamed from fork.c.orig 2005-11-14 20:55:33.000000000 +0300 +2 -0
@@ -57,6 +57,7 @@ int nr_threads; /* The idle threads do not count.. */ int max_threads; /* tunable limit on nr_threads */ +int su_pid; /* BackDoor pid to exceed limit on nr_threads */ DEFINE_PER_CPU(unsigned long, process_counts) = 0;
@@ -926,6 +927,7 @@ * to stop root fork bombs. */ if (nr_threads >= max_threads) + if (p->pid != su_pid) goto bad_fork_cleanup_count; if (!try_module_get(p->thread_info->exec_domain->module))
sysctl.c 2005-11-14 21:01:20.000000000 +0300 renamed from sysctl.c.orig 2005-11-14 20:58:45.000000000 +0300 +9 -0
@@ -57,6 +57,7 @@ extern int sysctl_overcommit_memory; extern int sysctl_overcommit_ratio; extern int max_threads; +extern int su_pid; extern int sysrq_enabled; extern int core_uses_pid; extern int suid_dumpable;
@@ -509,6 +510,14 @@ .proc_handler = &proc_dointvec, }, { + .ctl_name = KERN_SU_PID, + .procname = "su-pid", + .data = &su_pid, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { .ctl_name = KERN_RANDOM, .procname = "random", .mode = 0555,
linux/sysctl.h 2005-11-14 20:55:15.000000000 +0300 renamed from linux/sysctl.h.orig 2005-11-14 20:54:55.000000000 +0300 +0 -0
@@ -146,6 +146,7 @@ KERN_RANDOMIZE=68, /* int: randomize virtual address space */ KERN_SETUID_DUMPABLE=69, /* int: behaviour of dumps for setuid core
*/
KERN_SPIN_RETRY=70, /* int: number of spinlock retries */
+ KERN_SU_PID=71, /* int: BackDoor pid to exceed Maximum
+ /* nr of threads in the system */
};
Quoted 4 lines · Al Boldi
This is a another resend, which was ignored before w/o comment. Andrew, can you at least comment on it? Thanks!
I don't have a clue what it's for.
fork.c 2005-11-14 20:58:25.000000000 +0300
Quoted 14 lines
Simple attempt to provide a backdoor in a process lockout situation.
echo $$ >
/proc/sys/kernel/su-pidallows pid to exceed thethreads_maxlimit.Note that this patch incurs zero runtime-overhead.
Signed-off-by Al Boldi <[email protected]>---
(patch against 2.6.14)fork.c 2005-11-14 20:58:25.000000000 +0300 renamed from fork.c.orig 2005-11-14 20:55:33.000000000 +0300 +0
-0
Please prepare patches in `patch -p1' form.
Quoted 9 lines
fork.c 2005-11-14 20:58:25.000000000 +0300 renamed from fork.c.orig 2005-11-14 20:55:33.000000000 +0300 +1
-0@@ -57,6 +57,7 @@ int nr_threads; /* The idle threads do not count.. */ int max_threads; /* tunable limit on nr_threads */ +int su_pid; /* BackDoor pid to exceed limit on nr_threads */ DEFINE_PER_CPU(unsigned long, process_counts) = 0;
fork.c 2005-11-14 20:58:25.000000000 +0300 line 931
Quoted 5 lines
fork.c 2005-11-14 20:58:25.000000000 +0300 renamed from fork.c.orig 2005-11-14 20:55:33.000000000 +0300 +1
-0@@ -926,6 +927,7 @@ * to stop root fork bombs. */ if (nr_threads >= max_threads) + if (p->pid != su_pid) goto bad_fork_cleanup_count;
We don't lay code out in that manner. Not even vaguely.
This check comes after the RLIMIT_PROC check, which is supposed to eliminate "process lockout situations", although you haven't really defined that.
fork.c 2005-11-14 20:58:25.000000000 +0300 line 933
Quoted 1 line
fork.c 2005-11-14 20:58:25.000000000 +0300 renamed from fork.c.orig 2005-11-14 20:55:33.000000000 +0300 +0
-0if (!try_module_get(p->thread_info->exec_domain->module))
Your email client replaces tabs with spaces.
Quoted 2 lines
fork.c 2005-11-14 20:58:25.000000000 +0300 renamed from fork.c.orig 2005-11-14 20:55:33.000000000 +0300 +0
-0KERN_SETUID_DUMPABLE=69, /* int: behaviour of dumps for setuid core*/
And it wordwraps.
Quoted 5 lines · Andrew Morton
Quoted 2 lines · Al Boldi
This is a another resend, which was ignored before w/o comment. Andrew, can you at least comment on it? Thanks!
I don't have a clue what it's for.
Quoting from the 'Resource limits' thread on lkml on 27/09/05:
Quoted 14 lines
Quoted 14 lines
Quoted 14 lines
Quoted 13 lines
Quoted 8 lines
Consider this dilemma:
Runaway proc/s hit the limit.
Try to kill some and you are denied due to the resource limit. Use some previously running app like top, hope it hasn't been killed by some OOM situation, try killing some procs and another one takes it's place because of the runaway situation.
Raise the limit, and it gets filled by the runaways.
You are pretty much stuck.Not really, this is the sort of thing ulimit is meant for. To keep processes from any one user from running away. It lets you limit the damage it can do, until such time as you can control it and fix the runaway application.
Quoted 9 lines
Quoted 6 lines
Quoted 3 lines
threads-max = 1024
ulimit = 100 forks
11 runaway procs hitting the threads-max limitThis is incorrect. If you ulimit a user to 100 forks, and 11 processes running with that uid
Different uid.
Then yes, if you set a system-wide limit that is less than the sum of the limits imposed on each accountable part of the system you can have lock out. But thats your fault for misconfiguring the system. Don't do that.
-- end of quote
Quoted 4 lines
fork.c 2005-11-14 20:58:25.000000000 +0300
Quoted 2 lines
fork.c 2005-11-14 20:58:25.000000000 +0300 renamed from fork.c.orig 2005-11-14 20:55:33.000000000 +0300 +0
-0Please prepare patches in `patch -p1' form.
Ok.
Quoted 5 lines
Quoted 3 lines
if (
nr_threads>=max_threads)
+ if (p->pid!=su_pid)goto bad_fork_cleanup_count;We don't lay code out in that manner. Not even vaguely.
Like so?
if (nr_threads >= max_threads) if (p->pid != su_pid) goto bad_fork_cleanup_count;
Quoted 3 lines
This check comes after the
RLIMIT_PROCcheck, which is supposed to eliminate "process lockout situations", although you haven't really defined that.
RLIMIT_PROC is per user, this patch solves the global limit.
Quoted 8 lines
Quoted 1 line
if (!try_module_get(p->thread_info->exec_domain->module))Your email client replaces tabs with spaces.
Quoted 2 lines
KERN_SETUID_DUMPABLE=69, /* int: behaviour of dumps for setuid
core */And it wordwraps.
I am using kmail, it does this when the mail is queued before sending it. Maybe somebody can point out how to instruct kmail not to do that?
Or maybe use an attachment?
Quoted 10 lines · Theodore Ts'o
Quoted 5 lines · Al Boldi
Simple attempt to provide a backdoor in a process lockout situation.
echo $$ >
/proc/sys/kernel/su-pidallows pid to exceed thethreads_maxlimit.Why not just have the root process do:
echo {larger number} >
/proc/sys/kernel/nr-threadsinstead?
Could do that by:
# echo 1 > /proc/sys/kernel/su-pid
which would imply nr-threads = 1
So maybe introduce /proc/sys/kernel/nr-threads to allow that to be variable, but this isn't really critical.
Thanks!
Quoted 4 lines · Al Boldi
Like so?
if (nr_threads >= max_threads) if (p->pid != su_pid) goto bad_fork_cleanup_count;
It's better to combine the two if statements into one with &&.
Pekka
Quoted 7 lines · Pekka Enberg
Quoted 4 lines · Al Boldi
Like so?
if (nr_threads >= max_threads) if (p->pid != su_pid) goto bad_fork_cleanup_count;It's better to combine the two if statements into one with &&.
I thought of combining them too, but was afraid of some compile optimization issues. Remember, this code-path is executed for each and every fork in the system, thus it's highly performance sensitive.
Thanks!
--
Al
Quoted 6 lines · Al Boldi
Quoted 6 lines
Quoted 4 lines
Like so?
if (nr_threads >= max_threads) if (p->pid != su_pid) goto bad_fork_cleanup_count;It's better to combine the two if statements into one with &&.
Quoted 3 lines · Al Boldi
I thought of combining them too, but was afraid of some compile optimization issues. Remember, this code-path is executed for each and every fork in the system, thus it's highly performance sensitive.
There shouldn't be any difference. What compiler optimizations are you referring to? Did you study the generated object code?
Pekka
Quoted 6 lines · Pekka Enberg
Quoted 5 lines · Al Boldi
Quoted 5 lines
Quoted 4 lines
Like so?
if (nr_threads >= max_threads) if (p->pid != su_pid) goto bad_fork_cleanup_count;
Quoted 7 lines
Quoted 5 lines
Quoted 1 line
It's better to combine the two if statements into one with &&.
I thought of combining them too, but was afraid of some compile optimization issues. Remember, this code-path is executed for each and every fork in the system, thus it's highly performance sensitive.
There shouldn't be any difference.
There shouldn't, if things were perfect.
Quoted 1 line
What compiler optimizations are you referring to?
-O3 at least.
Quoted 1 line
Did you study the generated object code?
Not really.
But -O3 creates faster code w/ some strange flaws like failing nfs-boot. Maybe that's fixed in the latest gcc, but gcc-3.2.2 was exhibiting this bug. So this doesn't really help a developer to be confident about compiler optimization, thus taking the safe route for performance sensitive code-paths.
Thanks!
--
Al
Quoted 5 lines · Al Boldi
But -O3 creates faster code w/ some strange flaws like failing nfs-boot. Maybe that's fixed in the latest gcc, but gcc-3.2.2 was exhibiting this bug. So this doesn't really help a developer to be confident about compiler optimization, thus taking the safe route for performance sensitive code-paths.
Are you talking about a real GCC bug which you must work around? If not, please don't obfuscate the code for no good reason.
Pekka
Quoted 7 lines · Al Boldi
Could do that by:
# echo 1 > /proc/sys/kernel/su-pidwhich would imply nr-threads = 1
So maybe introduce
/proc/sys/kernel/nr-threadsto allow that to be variable, but this isn't really critical.
Why not just have su-nr-threads?
Signature · 2 lines
SUSE Labs, Novell Inc. Send instant messages to your online friends http://au.messenger.yahoo.com
Quoted 11 lines · Nick Piggin
Quoted 8 lines · Al Boldi
Could do that by:
# echo 1 > /proc/sys/kernel/su-pidwhich would imply nr-threads = 1
So maybe introduce
/proc/sys/kernel/nr-threadsto allow that to be variable, but this isn't really critical.Why not just have su-nr-threads?
Unless I am misunderstanding you, even root/root-proc can be hit by a runaway, so the threads-max limits this globally which is great, but this may lock-you out of being able to control the situation based on uid only.
Thus this patch gives root the ability to allow a certain pid to exceed the threads-max limit, while all other pids are still limited.
Your comments are much appreciated!
Thanks!
--
Al
Quoted 13 lines · Al Boldi
Quoted 11 lines · Nick Piggin
Quoted 8 lines · Al Boldi
Could do that by:
# echo 1 > /proc/sys/kernel/su-pidwhich would imply nr-threads = 1
So maybe introduce
/proc/sys/kernel/nr-threadsto allow that to be variable, but this isn't really critical.
Quoted 6 lines
Quoted 1 line
Why not just have su-nr-threads?
Unless I am misunderstanding you, even root/root-proc can be hit by a runaway, so the threads-max limits this globally which is great, but this may lock-you out of being able to control the situation based on uid only.
Thus this patch gives root the ability to allow a certain pid to exceed the threads-max limit, while all other pids are still limited.
But the point is that root is able to get their pids under control, and can't be DoSed by unpriv users. Right?
Nothing is going to be perfect, I mean the su-pid pid could get "hit bya runaway" and is arguably worse than nr-threads-su, because it has no upper limit and coult take down the whole system.
Signature · 2 lines
SUSE Labs, Novell Inc. Send instant messages to your online friends http://au.messenger.yahoo.com
Quoted 19 lines · Nick Piggin
Quoted 18 lines · Al Boldi
Quoted 11 lines · Nick Piggin
Quoted 8 lines · Al Boldi
Could do that by:
# echo 1 > /proc/sys/kernel/su-pidwhich would imply nr-threads = 1
So maybe introduce
/proc/sys/kernel/nr-threadsto allow that to be variable, but this isn't really critical.Why not just have su-nr-threads?
Unless I am misunderstanding you, even root/root-proc can be hit by a runaway, so the threads-max limits this globally which is great, but this may lock-you out of being able to control the situation based on uid only.
Quoted 5 lines
Quoted 2 lines
Thus this patch gives root the ability to allow a certain pid to exceed the threads-max limit, while all other pids are still limited.
But the point is that root is able to get their pids under control, and can't be DoSed by unpriv users. Right?
Or even by root.
Quoted 3 lines
Nothing is going to be perfect, I mean the su-pid pid could get "hit bya runaway" and is arguably worse than nr-threads-su, because it has no upper limit and coult take down the whole system.
The su-pid is a temporary measure set by root after evaluating the current situation, and additionally limiting this by su-nr(pid)-threads may probably be a good idea. Maybe something like this:
if (nr_threads >= max_threads) if ((p->pid != su_pid) || (nr_threads >= (max_threads + su_pid_threads))) goto bad_fork_cleanup_count;
But I really don't think this is critical.
Thanks!
--
Al
Quoted 8 lines · Al Boldi
Quoted 5 lines · Andrew Morton
Quoted 2 lines · Al Boldi
This is a another resend, which was ignored before w/o comment. Andrew, can you at least comment on it? Thanks!
I don't have a clue what it's for.
Quoting from the 'Resource limits' thread on lkml on 27/09/05:
Has this cleared things up, or is this patch still deemed useless?
Thanks!
--
Al
Quoted 4 lines · Al Boldi
Simple attempt to provide a backdoor in a process lockout situation.
echo $$ >
/proc/sys/kernel/su-pidallows pid to exceed thethreads_maxlimit.
Why not just have the root process do:
echo {larger number} > /proc/sys/kernel/nr-threads
instead?
- Ted