[lxc-devel] [lxc/master] capabilities: raise ambient capabilities

brauner on Github lxc-bot at linuxcontainers.org
Tue May 15 22:25:31 UTC 2018


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 418 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20180515/156dddd7/attachment.bin>
-------------- next part --------------
From 6938358ab3d2c741da51574b916d872f11b62244 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 15 May 2018 21:33:48 +0200
Subject: [PATCH] capabilities: raise ambient capabilities

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
Suggested-by: Jonathan Calmels <jcalmels at nvidia.com>
---
 src/lxc/caps.c | 56 +++++++++++++++++++++++++++++++++++++++
 src/lxc/caps.h | 83 ++++++++++++++++++++++++++++++++++------------------------
 src/lxc/conf.c |  6 +++++
 3 files changed, 111 insertions(+), 34 deletions(-)

diff --git a/src/lxc/caps.c b/src/lxc/caps.c
index 2d3261da0..0b94b2e2b 100644
--- a/src/lxc/caps.c
+++ b/src/lxc/caps.c
@@ -126,6 +126,62 @@ int lxc_caps_up(void)
 	return 0;
 }
 
+int lxc_ambient_caps_up(void)
+{
+	int ret;
+	cap_t caps;
+	cap_value_t cap;
+
+	/* When we are run as root, we don't want to play with the capabilities. */
+	if (!getuid())
+		return 0;
+
+	caps = cap_get_proc();
+	if (!caps) {
+		SYSERROR("Failed to retrieve capabilities");
+		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) {
+			if (errno == EINVAL) {
+				INFO("Last supported cap was %d", cap - 1);
+				break;
+			}
+
+			SYSERROR("Failed to retrieve capability flag");
+			goto out;
+		}
+
+		ret = cap_set_flag(caps, CAP_INHERITABLE, 1, &cap, flag);
+		if (ret) {
+			SYSERROR("Failed to set capability flag");
+			goto out;
+		}
+	}
+
+	ret = cap_set_proc(caps);
+	if (ret) {
+		SYSERROR("Failed to set capabilities");
+		goto out;
+	}
+
+	for (cap = 0; cap <= CAP_LAST_CAP; cap++) {
+		ret = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, cap, 0, 0);
+		if (ret < 0) {
+			SYSERROR("Failed to raise ambient capability %d", cap);
+			continue;
+		}
+	}
+
+out:
+	cap_free(caps);
+	return 0;
+}
+
 int lxc_caps_init(void)
 {
 	uid_t uid = getuid();
diff --git a/src/lxc/caps.h b/src/lxc/caps.h
index 2b3b1a502..ecabe4a85 100644
--- a/src/lxc/caps.h
+++ b/src/lxc/caps.h
@@ -27,70 +27,85 @@
 #include "config.h"
 #include <stdbool.h>
 
-
 #if HAVE_LIBCAP
 #include <linux/types.h> /* workaround for libcap < 2.17 bug */
 #include <sys/capability.h>
 
 extern int lxc_caps_down(void);
 extern int lxc_caps_up(void);
+extern int lxc_ambient_caps_up(void);
 extern int lxc_caps_init(void);
-
 extern int lxc_caps_last_cap(void);
-
 extern bool lxc_proc_cap_is_set(cap_value_t cap, cap_flag_t flag);
-extern bool lxc_file_cap_is_set(const char *path, cap_value_t cap, cap_flag_t flag);
+extern bool lxc_file_cap_is_set(const char *path, cap_value_t cap,
+				cap_flag_t flag);
 #else
-static inline int lxc_caps_down(void) {
+static inline int lxc_caps_down(void)
+{
+	return 0;
+}
+
+static inline int lxc_caps_up(void)
+{
 	return 0;
 }
-static inline int lxc_caps_up(void) {
+
+static inline int lxc_ambient_caps_up(void)
+{
 	return 0;
 }
-static inline int lxc_caps_init(void) {
+
+static inline int lxc_caps_init(void)
+{
 	return 0;
 }
 
-static inline int lxc_caps_last_cap(void) {
+static inline int lxc_caps_last_cap(void)
+{
 	return 0;
 }
 
 typedef int cap_value_t;
 typedef int cap_flag_t;
-static inline bool lxc_proc_cap_is_set(cap_value_t cap, cap_flag_t flag) {
+static inline bool lxc_proc_cap_is_set(cap_value_t cap, cap_flag_t flag)
+{
 	return false;
 }
 
-static inline bool lxc_file_cap_is_set(const char *path, cap_value_t cap, cap_flag_t flag) {
+static inline bool lxc_file_cap_is_set(const char *path, cap_value_t cap,
+				       cap_flag_t flag)
+{
 	return false;
 }
 #endif
 
-#define lxc_priv(__lxc_function)			\
-	({						\
-		__label__ out;				\
-		int __ret, __ret2, ___errno = 0;		\
-		__ret = lxc_caps_up();			\
-		if (__ret)				\
-			goto out;			\
-		__ret = __lxc_function;			\
-		if (__ret)				\
-			___errno = errno;		\
-		__ret2 = lxc_caps_down();		\
-	out:	__ret ? errno = ___errno,__ret : __ret2;	\
+#define lxc_priv(__lxc_function)                          \
+	({                                                \
+		__label__ out;                            \
+		int __ret, __ret2, ___errno = 0;          \
+		__ret = lxc_caps_up();                    \
+		if (__ret)                                \
+			goto out;                         \
+		__ret = __lxc_function;                   \
+		if (__ret)                                \
+			___errno = errno;                 \
+		__ret2 = lxc_caps_down();                 \
+	out:                                              \
+		__ret ? errno = ___errno, __ret : __ret2; \
 	})
 
-#define lxc_unpriv(__lxc_function)			\
-	({						\
-		__label__ out;				\
-		int __ret, __ret2, ___errno = 0;		\
-		__ret = lxc_caps_down();		\
-		if (__ret)				\
-			goto out;			\
-		__ret = __lxc_function;			\
-		if (__ret)				\
-			___errno = errno;		\
-		__ret2 = lxc_caps_up();			\
-	out:	__ret ? errno = ___errno,__ret : __ret2;	\
+#define lxc_unpriv(__lxc_function)                        \
+	({                                                \
+		__label__ out;                            \
+		int __ret, __ret2, ___errno = 0;          \
+		__ret = lxc_caps_down();                  \
+		if (__ret)                                \
+			goto out;                         \
+		__ret = __lxc_function;                   \
+		if (__ret)                                \
+			___errno = errno;                 \
+		__ret2 = lxc_caps_up();                   \
+	out:                                              \
+		__ret ? errno = ___errno, __ret : __ret2; \
 	})
 #endif
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 5c66c6f35..000eac568 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -3337,6 +3337,12 @@ int lxc_setup(struct lxc_handler *handler)
 	const char *lxcpath = handler->lxcpath, *name = handler->name;
 	struct lxc_conf *lxc_conf = handler->conf;
 
+	ret = lxc_ambient_caps_up();
+	if (ret < 0) {
+		WARN("Failed to raise ambient capabilities");
+		return -1;
+	}
+
 	ret = do_rootfs_setup(lxc_conf, name, lxcpath);
 	if (ret < 0) {
 		ERROR("Failed to setup rootfs");


More information about the lxc-devel mailing list