[PATCH] limit process tree depth

From: Marco Molinaro
Date: Mon Mar 08 2004 - 11:04:41 EST


Description : Limit the depth of the process tree
Kernel version : 2.6.3
URL : http://oss.digirati.com.br/fkdepth/

This patch provides limiting facility over the creation of children
processes.
That means if a process depth is set to:
0 - it can't fork.
1 - it can fork, but its children can't.
2 - the process and its children can fork, but its grandchildren can't.
3 - etc.

It's done using the rlimit framework, which makes the patch really small.
One application is to stop the following exploit:

Mod_php under apache httpd 2.0.x leaks a critical file descriptor that can be
used to hijack the https service. To do so, the proccess needs to fork and

deamonize itself. By setting his process depth to 0 or 1, it just can't
deamonize.

This patch only shows the changes for i386 arch to reduce this mail size,
full
version (all archs) can be found at URL.

Since it's my very first patch attempt I hope I haven't messed it up. Any
comments and sugestions are appreciated.

Marco


diff -Nur linux-2.6.3/include/asm-i386/resource.h
linux/include/asm-i386/resource.h
--- linux-2.6.3/include/asm-i386/resource.h 2004-02-18 00:57:16.000000000
-0500
+++ linux/include/asm-i386/resource.h 2004-03-07 14:00:09.000000000 -0500
@@ -16,8 +16,9 @@
#define RLIMIT_MEMLOCK 8 /* max locked-in-memory address space */
#define RLIMIT_AS 9 /* address space limit */
#define RLIMIT_LOCKS 10 /* maximum file locks held */
+#define RLIMIT_DEPTH 11 /* max process depth */

-#define RLIM_NLIMITS 11
+#define RLIM_NLIMITS 12

/*
* SuS says limits have to be unsigned.
@@ -40,6 +41,7 @@
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
{ RLIM_INFINITY, RLIM_INFINITY }, \
+ { RLIM_INFINITY, RLIM_INFINITY }, \
}

#endif /* __KERNEL__ */
diff -Nur linux-2.6.3/kernel/fork.c linux/kernel/fork.c
--- linux-2.6.3/kernel/fork.c 2004-02-18 00:57:14.000000000 -0500
+++ linux/kernel/fork.c 2004-03-07 13:56:45.000000000 -0500
@@ -1008,6 +1008,20 @@
p->real_parent = current;
p->parent = p->real_parent;

+
+ /*
+ * Check if the RLIMIT_DEPTH was set and then if parent
+ * have a spare depth. Finally update child's depth limits.
+ */
+ if (p->parent->rlim[RLIMIT_DEPTH].rlim_cur != RLIM_INFINITY) {
+ if (!p->parent->rlim[RLIMIT_DEPTH].rlim_cur) {
+ retval = -EPERM;
+ goto bad_fork_cleanup_namespace;
+ }
+ p->rlim[RLIMIT_DEPTH].rlim_cur = p->parent->rlim[RLIMIT_DEPTH].rlim_cur
- 1;
+ p->rlim[RLIMIT_DEPTH].rlim_max = p->parent->rlim[RLIMIT_DEPTH].rlim_max
- 1;
+ }
+
if (clone_flags & CLONE_THREAD) {
spin_lock(&current->sighand->siglock);
/*
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/