PATCH/RFC - process limits problem

Neil Brown (neilb@cse.unsw.edu.au)
Mon, 12 May 2003 12:11:59 +1000


Here is the problem:
We have a multi-user server that has lots of people logging on to
it and doing all sorts of weird things. To help keep them contained
we set the per-user process limit to 256.
If this server happens to have 256 or more processes running as root
(which happens from time to time), then ordinary users cannot
run "lpr" (lprng version) because it tries to fork and fails: EAGAIN.

What appears to be happening is lpr tries to fork while it has it's
effective uid restored to the calling user's uid, but it's real user
is still root.

Because real uid is root, process accounting is done against root's
processes, and because euid is not root, capabilities have been
dropped and the process is not allowed to exceed this limit.

This doesn't seem fair: to count the usage as though the process were
root, but to limit it as though the process wasn't root.

It is not obvious to me how best to fix this problem.
One approach would be to modify lpr to use capset(2) to claim
CAP_SYS_RESOURCE before forking, but this seems to be fixing the
symptom rather than the problem.

Another approach is embodied in the patch below which makes a special
case for root_user and not to impose any limits on root. I think
this is better but I would appreciate hearing other perspectives.

In brief, my view is that it seems odd to use per-process attibutes
(such as capabilites and even rlim) when limiting a per-user resource,
such as number of processes. I appreciate that for compatability
reasons we really have to store the limit per-process rather than
per-user, but I don't think it makes sense to use a per-process
capability to over-ride a per-user limit. It should be a per-user
capability.

NeilBrown

diff ./kernel/fork.c~current~ ./kernel/fork.c
--- ./kernel/fork.c~current~ 2003-05-12 11:51:28.000000000 +1000
+++ ./kernel/fork.c 2003-05-12 11:53:44.000000000 +1000
@@ -636,6 +636,7 @@ int do_fork(unsigned long clone_flags, u
* than the amount of processes root is running. -- Rik
*/
if (atomic_read(&p->user->processes) >= p->rlim[RLIMIT_NPROC].rlim_cur
+ && p->user != &root_user
&& !capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE))
goto bad_fork_free;

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/