diff options
author | Nick Kralevich <nnk@google.com> | 2013-06-19 17:20:24 -0700 |
---|---|---|
committer | Nick Kralevich <nnk@google.com> | 2013-06-19 17:23:14 -0700 |
commit | ab3df62f7b5584af6dee4f5ec069b70dd4f4cee6 (patch) | |
tree | 5677af11080496520b9780db6b469eedc41f7b5d | |
parent | 3911886e854d31058e7d3a6e310e8eafd06c02e0 (diff) | |
download | netd-ab3df62f7b5584af6dee4f5ec069b70dd4f4cee6.tar.gz |
netd: reduce privileges
netd doesn't need full root capabilities. Rather, it only needs
CAP_NET_ADMIN and CAP_NET_RAW. Reduce the capabilities to that
set.
netd continues to run with UID=0, which allows applications spawned
by netd to continue to have CAP_NET_ADMIN and CAP_NET_RAW. It also
allows netd to access /proc and /sys files as UID=0.
Change-Id: I439d22150109697213c0cc83276ddb668007b978
-rw-r--r-- | main.cpp | 39 |
1 files changed, 39 insertions, 0 deletions
@@ -22,6 +22,8 @@ #include <sys/stat.h> #include <sys/types.h> #include <sys/wait.h> +#include <sys/capability.h> +#include <linux/prctl.h> #include <fcntl.h> #include <dirent.h> @@ -39,6 +41,42 @@ static void coldboot(const char *path); static void sigchld_handler(int sig); static void blockSigpipe(); +static void dropPrivileges() { + struct __user_cap_header_struct header; + struct __user_cap_data_struct cap[2]; + int i; + int result; + + // First drop unneeded capabilities from our bounding set, + // which affects children we exec. + for (i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0; i++) { + if (i == CAP_NET_ADMIN || i == CAP_NET_RAW) { + continue; + } + result = prctl(PR_CAPBSET_DROP, i, 0, 0, 0); + if (result != 0) { + perror("PR_CAPBSET_DROP failed: unable to drop privileges"); + exit(1); + } + } + + // Then drop capabilities from the current process. + memset(&header, 0, sizeof(header)); + memset(cap, 0, sizeof(cap)); + + header.version = _LINUX_CAPABILITY_VERSION_3; + header.pid = 0; + cap[CAP_TO_INDEX(CAP_NET_ADMIN)].effective |= CAP_TO_MASK(CAP_NET_ADMIN); + cap[CAP_TO_INDEX(CAP_NET_ADMIN)].permitted |= CAP_TO_MASK(CAP_NET_ADMIN); + cap[CAP_TO_INDEX(CAP_NET_RAW)].effective |= CAP_TO_MASK(CAP_NET_RAW); + cap[CAP_TO_INDEX(CAP_NET_RAW)].permitted |= CAP_TO_MASK(CAP_NET_RAW); + result = capset(&header, cap); + if (result != 0) { + perror("capset failed: unable to drop privileges"); + exit(1); + } +} + int main() { CommandListener *cl; @@ -47,6 +85,7 @@ int main() { MDnsSdListener *mdnsl; ALOGI("Netd 1.0 starting"); + dropPrivileges(); // signal(SIGCHLD, sigchld_handler); blockSigpipe(); |