summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Kralevich <nnk@google.com>2013-06-19 17:20:24 -0700
committerNick Kralevich <nnk@google.com>2013-06-19 17:23:14 -0700
commitab3df62f7b5584af6dee4f5ec069b70dd4f4cee6 (patch)
tree5677af11080496520b9780db6b469eedc41f7b5d
parent3911886e854d31058e7d3a6e310e8eafd06c02e0 (diff)
downloadnetd-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.cpp39
1 files changed, 39 insertions, 0 deletions
diff --git a/main.cpp b/main.cpp
index b466e423..e86a58b8 100644
--- a/main.cpp
+++ b/main.cpp
@@ -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();