One of the prerequisites for seccomp filter is the new PR_SET_NO_NEW_PRIVS prctl from Andy Lutomirski.
If you’re not interested in digging into creating a seccomp filter for your program, but you know your program should be effectively a “leaf node” in the process tree, you can call PR_SET_NO_NEW_PRIVS (nnp) to make sure that the current process and its children can not gain new privileges (like through running a setuid binary). This produces some fun results, since things like the “ping” tool expect to gain enough privileges to open a raw socket. If you set nnp to “1”, suddenly that can’t happen any more.
Here’s a quick example that sets nnp, and tries to run the command line arguments:
#include <stdio.h>
#include <unistd.h>
#include <sys/prctl.h>
#ifndef PR_SET_NO_NEW_PRIVS
# define PR_SET_NO_NEW_PRIVS 38
#endif
int main(int argc, char * argv[])
{
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
perror("prctl(NO_NEW_PRIVS)");
return 1;
}
return execvp(argv[1], &argv[1]);
}
When it tries to run ping, the setuid-ness just gets ignored:
$ gcc -Wall nnp.c -o nnp $ ./nnp ping -c1 localhost ping: icmp open socket: Operation not permitted
So, if your program has all the privs its going to need, consider using nnp to keep it from being a potential gateway to more trouble. Hopefully we can ship something like this trivial nnp helper as part of coreutils or similar, like nohup, nice, etc.
© 2012, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 License.
This is quite awesome. I don’t have a system running a modern-enough kernel to test; how does this interact with effective id changes? For example, if I set the euid to something, call prctl, then restore my saved euid, what happens?
Comment by James Brown — March 26, 2012 @ 2:55 pm
How is this different from just using caps+securebits?
Comment by jww — April 18, 2012 @ 3:37 pm
@James: looks like you can restore euid of 0. Not sure if that is intentional or not.
@jww: securebits (specifically SECURE_NOROOT_LOCKED) will keep a process from gaining capabilities, but not changing uid. nnp will block setuid transitions of any kind:
-rwsrwxr-x 1 root kees 8485 Apr 18 17:34 getuid
-rwxrwxr-x 1 kees kees 8637 Apr 18 17:36 nnp
$ ./getuid
euid:0 uid:501
$ ./nnp ./getuid
euid:501 uid:501
Comment by kees — April 18, 2012 @ 4:38 pm