Re: kmod, fork errors, net-pf-5 -- 2.1.89++

Mikael Pettersson (mikpe@csd.uu.se)
Fri, 24 Jul 1998 11:09:13 +0200 (MET DST)


On Thu, 23 Jul 1998, Les Schaffer wrote:

>I have had problems upgrading dev. kernels since some time after
>2.1.89, due to a problem associated with kmod.
>...
>Jul 22 10:20:51 localhost kernel: kmod: fork failed (module: net-pf-5), errno 11
>...
>alias net-pf-5 off # forget appletalk
>
>yet kmod still gives a fork error.

Please try the patch below. I'm using it myself since two weeks.

Explanation:

kernel_thread() invokes do_fork(), which calls find_empty_process(),
which calls charge_uid(current, 1) and checks for error (EAGAIN).
Since we change current->uid to zero, the original uid doesn't get
refunded in exit.c:release(), eventually leading to fork() returning
EAGAIN for that uid. [Thanks to Daniel R Risacher for pointing this
out in linux-kernel two weeks ago.]

This patch doesn't do a "charge_uid(current, 1)" after setting
current->uid to zero, because (a) root's uid count is not checked
by fork() (see find_empty_process()), (b) root's uid count is not
even correct, and (c) the potential over- or underflow should be
harmless on sane machines.

Kmod/fork will still return an error if the user's # of processes
is at that uid's max. This will probably show up as an error return
from the system call that needed the module. Tough.

Ideally, we ought to have a private flag to kernel_thead/do_fork
telling them not to bother with the charge_uid() check, but this
won't work since several architectures implement kernel_thread() as
a regular system call, and do_fork() can't easily check if the caller
happens to be request_module() and not some user trying to cheat..

Setting current->uid to zero already in request_module() is also not
a good idea; what if we sleep or if the user has an interval timer
alarm and a signal handler?

/Mikael

--- linux-2.1.110/kernel/kmod.c.~1~ Fri Jul 17 21:19:53 1998
+++ linux-2.1.110/kernel/kmod.c Fri Jul 24 10:01:46 1998
@@ -67,6 +67,9 @@
if (current->files->fd[i]) close(i);
}

+ /* kernel_thread() -> ... -> charge_uid(current, 1) workaround */
+ charge_uid(current, -1);
+
/* Give kmod all privileges.. */
current->uid = current->euid = current->fsuid = 0;
cap_set_full(current->cap_inheritable);

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.altern.org/andrebalsa/doc/lkml-faq.html