Subject: remove/restore effective capabilities
From: Daniel Lezcano <dlezcano@fr.ibm.com

This patch adds the functions to drop the 'effective' capabilities and
restore them from the 'permitted' capabilities.

When the command is run as 'root' we do nothing.
When the command is run as 'lambda' user, we drop the effective capabilities
When the command is run as 'root' but real uid is not root, we keep the capabilies,
switch to real uid, and drop the effective capabilities.

This approach is compatible for root user, lambda + file capabilities
and lambda + setuid.

Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
---
 src/lxc/Makefile.am |    2 
 src/lxc/caps.c      |  135 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/lxc/caps.h      |   28 ++++++++++
 3 files changed, 165 insertions(+)

Index: lxc/src/lxc/Makefile.am
===================================================================
--- lxc.orig/src/lxc/Makefile.am
+++ lxc/src/lxc/Makefile.am
@@ -5,6 +5,7 @@ pkginclude_HEADERS = \
 		monitor.h \
 		utils.h \
 		namespace.h \
+		caps.h \
 		lxc.h \
 		cgroup.h \
 		conf.h \
@@ -44,6 +45,7 @@ liblxc_so_SOURCES = \
         rtnl.c rtnl.h \
         genl.c genl.h \
 	\
+	caps.c caps.h \
 	mainloop.c mainloop.h \
 	af_unix.c af_unix.h \
 	\
Index: lxc/src/lxc/caps.c
===================================================================
--- /dev/null
+++ lxc/src/lxc/caps.c
@@ -0,0 +1,135 @@
+/*
+ * lxc: linux Container library
+ *
+ * (C) Copyright IBM Corp. 2007, 2008
+ *
+ * Authors:
+ * Daniel Lezcano <dlezcano at fr.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <sys/prctl.h>
+#include <sys/capability.h>
+
+#include "log.h"
+
+lxc_log_define(lxc_caps, lxc);
+
+int lxc_caps_down(void)
+{
+	cap_t caps;
+	int ret;
+
+	caps = cap_get_proc();
+	if (!caps) {
+		ERROR("failed to cap_init: %m");
+		return -1;
+	}
+
+	ret = cap_clear_flag(caps, CAP_EFFECTIVE);
+	if (ret) {
+		ERROR("failed to cap_clear_flag: %m");
+		goto out;
+	}
+
+	ret = cap_set_proc(caps);
+	if (ret) {
+		ERROR("failed to cap_set_proc: %m");
+		goto out;
+	}
+
+out:
+	cap_free(caps);
+        return 0;
+}
+
+int lxc_caps_up(void)
+{
+	cap_t caps;
+	cap_value_t cap;
+	int ret;
+
+	caps = cap_get_proc();
+	if (!caps) {
+		ERROR("failed to cap_init: %m");
+		return -1;
+	}
+
+	for (cap = 0; cap <= CAP_LAST_CAP; cap++) {
+
+		cap_flag_value_t flag;
+
+		ret = cap_get_flag(caps, cap, CAP_PERMITTED, &flag);
+		if (ret) {
+			ERROR("failed to cap_get_flag: %m");
+			goto out;
+		}
+
+		ret = cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap, flag);
+		if (ret) {
+			ERROR("failed to cap_set_flag: %m");
+			goto out;
+		}
+	}
+
+	ret = cap_set_proc(caps);
+	if (ret) {
+		ERROR("failed to cap_set_proc: %m");
+		goto out;
+	}
+
+out:
+	cap_free(caps);
+        return 0;
+}
+
+int lxc_caps_init(void)
+{
+	uid_t uid = getuid();
+	gid_t gid = getgid();
+	uid_t euid = geteuid();
+
+	if (!uid) {
+		INFO("command is run as 'root'");
+		return 0;
+	}
+
+	if (uid && !euid) {
+		INFO("command is run as setuid root (uid : %d)", uid);
+
+		if (prctl(PR_SET_KEEPCAPS, 1)) {
+			ERROR("failed to 'PR_SET_KEEPCAPS': %m");
+			return -1;
+		}
+
+		if (setresgid(gid, gid, gid)) {
+			ERROR("failed to change gid to '%d': %m", gid);
+			return -1;
+		}
+
+		if (setresuid(uid, uid, uid)) {
+			ERROR("failed to change uid to '%d': %m", uid);
+			return -1;
+		}
+	}
+
+	if (uid == euid)
+		INFO("command is run as user '%d'", uid);
+
+	return lxc_caps_down();
+}
Index: lxc/src/lxc/caps.h
===================================================================
--- /dev/null
+++ lxc/src/lxc/caps.h
@@ -0,0 +1,28 @@
+/*
+ * lxc: linux Container library
+ *
+ * (C) Copyright IBM Corp. 2007, 2008
+ *
+ * Authors:
+ * Daniel Lezcano <dlezcano at fr.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef _caps_h
+#define _caps_h
+int lxc_caps_down(void);
+int lxc_caps_up(void);
+int lxc_caps_init(void);
+#endif
