If your program runs with an effective user ID, then you have root privileges.
Linux capabilities fall into three sets: inherited, allowed, and efficient. Inheritable defines which features remain valid in exec() . Allowed determines which features are allowed for the process. Effective determines which opportunities are currently in place.
Edited to add: when a file system containing a binary file that will be exec() 'd supports the capabilities of the file system, they always affect what capabilities will be executed during execution. See Converting features during execve() to the man 7 man page features .
If you change the owner or group of processes from root to non-root, the effective set of functions is always cleared. By default, the allowed feature set is also allowed, but the caller prctl(PR_SET_KEEPCAPS, 1L) before changing the identifier tells the kernel to keep the allowed prctl(PR_SET_KEEPCAPS, 1L) set intact.
Therefore, in order to be able to CAP_NET_RAW , your program must have it in both allowed and effective sets. If you want CAP_NET_RAW remain valid over exec() , it must be included in all three feature sets.
Edited to add: if file capabilities are supported for the exec() target, file capabilities should also contain these capabilities in legacy and efficient suites. (Only the inclusion of capabilities in inherited and effective sets does not provide an opportunity, since it is not in the allowed set in the file capabilities, but it is enough to allow the transfer of the opportunity by the executor execee, if the executor has the opportunity).
You can use the setcap command to provide certain features to a binary file. (Most Linux file systems currently support these file capabilities.) This should not be privileged or setuid. Do not forget to add the necessary features for both allowed and effective sets.
Edited to add a few examples:
Grant CAP_NET_RAW to /usr/bin/myprog (which should NOT be setuid or setgid root):
sudo setcap 'cap_net_raw=pe' /usr/bin/myprog
By default, do not provide CAP_NET_RAW /usr/bin/myprog , but if the executor has the opportunity (both inherited and allowed sets), keep the possibility (inherited and allowed sets and activating them in an effective set):
sudo setcap 'cap_net_raw=ie' /usr/bin/myprog
If in any case your program should be installed as root, you can use, for example,
#define _GNU_SOURCE #include <unistd.h> #include <sys/types.h> #include <sys/capability.h> #include <sys/prctl.h> #define NEED_CAPS 1 static const cap_value_t need_caps[NEED_CAPS] = { CAP_NET_RAW }; int main(void) { uid_t real = getuid(); cap_t caps; /* Elevate privileges */ if (setresuid(0, 0, 0)) return 1; /* Fatal error, probably not setuid root */ /* Add need_caps to current capabilities. */ caps = cap_get_proc(); if (cap_set_flag(caps, CAP_PERMITTED, NEED_CAPS, need_caps, CAP_SET) || cap_set_flag(caps, CAP_EFFECTIVE, NEED_CAPS, need_caps, CAP_SET) || cap_set_flag(caps, CAP_INHERITABLE, NEED_CAPS, need_caps, CAP_SET)) return 1; /* Fatal error */ /* Update capabilities */ if (cap_set_proc(caps)) return 1; /* Fatal error */ /* Retain capabilities over an identity change */ if (prctl(PR_SET_KEEPCAPS, 1L)) return 1; /* Fatal error */ /* Return to original, real-user identity */ if (setresuid(real, real, real)) return 1; /* Fatal error */ /* Because the identity changed, we need to * re-install the effective set. */ if (cap_set_proc(caps)) return 1; /* Fatal error */ /* Capability set is no longer needed. */ cap_free(caps); /* You now have the CAP_NET_RAW capability. * It will be retained over fork() and exec(). */ return 0; }