codeblog code is freedom — patching my itch

March 26, 2012

keeping your process unprivileged

Filed under: Blogging,Chrome OS,Debian,Security,Ubuntu,Ubuntu-Server — kees @ 1:17 pm

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.
CC BY-SA 4.0

3 Comments

  1. 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

  2. How is this different from just using caps+securebits?

    Comment by jww — April 18, 2012 @ 3:37 pm

  3. @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

Powered by WordPress