grsec RLIMIT_NPROC handling incompatible with apache+suexec
Posted: Thu May 29, 2014 6:37 am
This is discussed elsewhere: viewtopic.php?f=3&t=3446&p=14021#p14021
But I'm posting it as a new topic, because it actually breaks apache+suexec+limits in a major way. I'm even surprised this isn't reported already. Copy paste what's going on from the other thread:
After pathing with latest grsecurity the program (apache) flow is as follows:
With default kernel behaviour we are getting failure at step 5, because PF_NPROC_EXCEEDED flag is raised at step 4.
With latest grsecurity we get failure at step 3, probably because PF_NPROC_EXCEEDED flag is raised at step 2. This is problematic, because at step 3 we are still not running as the final web user and limit is not enforced against this web user's process count.
Here's a strace excerpt:
Our current solution is to just revert the patch.
But I'm posting it as a new topic, because it actually breaks apache+suexec+limits in a major way. I'm even surprised this isn't reported already. Copy paste what's going on from the other thread:
After pathing with latest grsecurity the program (apache) flow is as follows:
- Code: Select all
step syscall uid comment
-1 fork() root apache master process spawns a connection handling child
0 setuid() apache privileges revoked (child has open fds etc.)
1 fork() apache apache child prepares to serve a cgi by spawning another child (to be replaced later w/ execve())
2 setrlimit() apache the new apache child sets rlimit_nproc in accordance with httpd.conf for this user's vhost
3 execve() apache the cgi child is replaced by the suexec binary (which is suid root)
4 setuid() root suexec changes its uid in accordance with this user's vhost SuexecUserGroup directive
5 execve() user actual cgi binary is called (e.g. php-cgi)
With default kernel behaviour we are getting failure at step 5, because PF_NPROC_EXCEEDED flag is raised at step 4.
With latest grsecurity we get failure at step 3, probably because PF_NPROC_EXCEEDED flag is raised at step 2. This is problematic, because at step 3 we are still not running as the final web user and limit is not enforced against this web user's process count.
Here's a strace excerpt:
- Code: Select all
[pid 7523] clone(Process 7546 attached
...
[pid 7546] chdir("/home/user/www/") = 0
[pid 7546] setrlimit(RLIMIT_CPU, {rlim_cur=60, rlim_max=60}) = 0
[pid 7546] setrlimit(RLIMIT_NPROC, {rlim_cur=20, rlim_max=20}) = 0
[pid 7546] setrlimit(RLIMIT_AS, {rlim_cur=128000000, rlim_max=128000000}) = 0
[pid 7546] execve("suexec", ["suexec", "1110", "2099", "sleep.php"], [/* 26 vars */]) = -1 EAGAIN (Resource temporarily unavailable)
...
Our current solution is to just revert the patch.