c++linuxlinux-capabilities

Linux capabilities to launch process as root from a user mode program in C++


I am trying to launch a child-process as root from a non-root parent-process. I am thinking to use capabilities to make that work.

What I have tried so far is that, have set the file cap permitted for parent process to cap_setgid,cap_setuid,capkill+p. Then on the same parent process, I am programmatically setting the same capabilities to effective capability of the process before calling fork+exec from the parent process.

For sanity check, I have changed the chmod permission of my child-process to load as root only chmod 4755. Thus, it will only be executed as root and nothing else.

I am seeing that with these a setup, I am not been able to load the child process at all. Can anyone help me understand, what am I misisng here?


Solution

  • Try this (parent.cc):

    #include <iostream>
    #include <sys/capability.h>
    #include <unistd.h>
    
    int main() {
        cap_t caps = cap_get_proc();
        cap_value_t val = CAP_SETUID;
        cap_set_flag(caps, CAP_EFFECTIVE, 1, &val, CAP_SET);
        if (cap_set_proc(caps)) {
            perror("failed to raise cap_setuid");
            exit(1);
        }
        if (setuid(0)) {
            perror("unable to setuid");
            exit(1);
        }
        execl("./child.sh", "child.sh", NULL);
        std::cout << "didn't work, uid=" << getuid();
        exit(1);
    }
    

    With this (child.sh):

    #!/bin/bash
    id -u
    

    Build and set things up:

    $ chmod +x child.sh
    $ g++ -o parent parent.cc -lcap
    $ sudo setcap cap_setuid=p ./parent
    

    If you run ./parent it should work like this:

    $ ./parent 
    0
    

    This example is single threaded. If your app is single threaded, it should be sufficient. If your program is multithreaded, you might need to explore something like libpsx.