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