I'm trying to understand how Linux capabilities are passed to a process that has been exec()
'd by another one. From what I've read, in order for a capability to be kept after exec, it must be in the inheritable set. What I am not sure of, though, is how that set gets populated.
My goal is to be able to run a program as a regular user that would normally require root. The capability it needs is cap_dac_override
so it can read a private file. I do not want to give it any other capabilities.
Here's my wrapper:
#include <unistd.h>
int main(int argc, char *argv[]) {
return execl("/usr/bin/net", "net", "ads", "dns", "register", "-P", NULL);
}
This works when I set the setuid permission on the resulting executable:
~ $ sudo chown root: ./registerdns
~ $ sudo chmod u+s ./registerdns
~ $ ./registerdns
Successfully registered hostname with DNS
I would like to use capabilities instead of setuid, though. I've tried setting the cap_dac_override
capability on the wrapper:
~ $ sudo setcap cap_dac_override=eip ./registerdns
~ $ ./registerdns
Failed to open /var/lib/samba/private/secrets.tdb
ERROR: Unable to open secrets database
I've also tried setting the inheritable flag on the cap_dac_override
capability for the net
executable itself:
~ $ sudo setcap cap_dac_override=eip ./registerdns
~ $ sudo setcap cap_dac_override=i /usr/bin/net
~ $ ./registerdns
Failed to open /var/lib/samba/private/secrets.tdb
ERROR: Unable to open secrets database
I need to use the wrapper to ensure that the capability is only available when using that exact set of arguments; the net
program does several other things that could be dangerous to give users too broad of permissions on it.
I'm obviously misunderstanding how the inheritance works. I can't seem to figure out how to set up the wrapper to pass its capabilities along to the replacement process so it can use them. I've read the man page, and countless other documents on how it should work, and I thought I was doing what it describes.
net
binary and see if that fixes it.