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