[lxc-devel] [lxcfs/master] cgroup_fuse: fix cgroupfs virtualization needed on non-cgns systems

brauner on Github lxc-bot at linuxcontainers.org
Mon Mar 16 12:20:14 UTC 2020


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 365 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20200316/cfb4d3d1/attachment.bin>
-------------- next part --------------
From 1e6143f9f3a703a6bfe12be967ece81e83401b97 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Mon, 16 Mar 2020 13:18:57 +0100
Subject: [PATCH] cgroup_fuse: fix cgroupfs virtualization needed on non-cgns
 systems

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/cgroup_fuse.c    | 52 +++++++++++++++++++++++++++++++++-----------
 src/cgroups/cgfsng.c |  4 ++--
 src/cgroups/cgroup.h |  1 +
 src/lxcfs.c          | 25 +++++++++++++++++----
 src/macro.h          |  1 +
 5 files changed, 64 insertions(+), 19 deletions(-)

diff --git a/src/cgroup_fuse.c b/src/cgroup_fuse.c
index 2130d7a..2e4aa2c 100644
--- a/src/cgroup_fuse.c
+++ b/src/cgroup_fuse.c
@@ -60,6 +60,32 @@ struct pid_ns_clone_args {
 	int (*wrapped) (int, pid_t);
 };
 
+static inline int get_cgroup_fd_handle_named(const char *controller)
+{
+	if (strcmp(controller, "systemd") == 0)
+		return get_cgroup_fd("name=systemd");
+
+	return get_cgroup_fd(controller);
+}
+
+static char *get_pid_cgroup_handle_named(pid_t pid, const char *controller)
+{
+	if (strcmp(controller, "systemd") == 0)
+		return get_pid_cgroup(pid, "name=systemd");
+
+	return get_pid_cgroup(pid, controller);
+}
+
+static bool get_cgroup_handle_named(struct cgroup_ops *ops,
+				    const char *controller, const char *cgroup,
+				    const char *file, char **value)
+{
+	if (strcmp(controller, "systemd") == 0)
+		return cgroup_ops->get(ops, "name=systemd", cgroup, file, value);
+
+	return cgroup_ops->get(cgroup_ops, controller, cgroup, file, value);
+}
+
 /*
  * given /cgroup/freezer/a/b, return "freezer".
  * the returned char* should NOT be freed.
@@ -144,7 +170,7 @@ static bool is_child_cgroup(const char *controller, const char *cgroup, const ch
 	int ret;
 	struct stat sb;
 
-	cfd = get_cgroup_fd(controller);
+	cfd = get_cgroup_fd_handle_named(controller);
 	if (cfd < 0)
 		return false;
 
@@ -176,7 +202,7 @@ static bool caller_may_see_dir(pid_t pid, const char *contrl, const char *cg)
 	if (strcmp(cg, "/") == 0 || strcmp(cg, "./") == 0)
 		return true;
 
-	c2 = get_pid_cgroup(pid, contrl);
+	c2 = get_pid_cgroup_handle_named(pid, contrl);
 	if (!c2)
 		return false;
 	prune_init_slice(c2);
@@ -251,7 +277,7 @@ static char *get_next_cgroup_dir(const char *taskcg, const char *querycg)
 static bool caller_is_in_ancestor(pid_t pid, const char *contrl, const char *cg, char **nextcg)
 {
 	bool answer = false;
-	char *c2 = get_pid_cgroup(pid, contrl);
+	char *c2 = get_pid_cgroup_handle_named(pid, contrl);
 	char *linecmp;
 
 	if (!c2)
@@ -293,7 +319,7 @@ static struct cgfs_files *cgfs_get_key(const char *controller,
 	struct stat sb;
 	struct cgfs_files *newkey;
 
-	cfd = get_cgroup_fd(controller);
+	cfd = get_cgroup_fd_handle_named(controller);
 	if (cfd < 0)
 		return false;
 
@@ -659,7 +685,7 @@ static int cgfs_create(const char *controller, const char *cg, uid_t uid, gid_t
 	size_t len;
 	char *dirnam;
 
-	cfd = get_cgroup_fd(controller);
+	cfd = get_cgroup_fd_handle_named(controller);
 	if (cfd < 0)
 		return -EINVAL;
 
@@ -807,7 +833,7 @@ static bool cgfs_remove(const char *controller, const char *cg)
 	char *dirnam;
 	bool bret;
 
-	cfd = get_cgroup_fd(controller);
+	cfd = get_cgroup_fd_handle_named(controller);
 	if (cfd < 0)
 		return false;
 
@@ -897,7 +923,7 @@ static bool cgfs_chmod_file(const char *controller, const char *file, mode_t mod
 	size_t len;
 	char *pathname;
 
-	cfd = get_cgroup_fd(controller);
+	cfd = get_cgroup_fd_handle_named(controller);
 	if (cfd < 0)
 		return false;
 
@@ -1016,7 +1042,7 @@ static int cgfs_chown_file(const char *controller, const char *file, uid_t uid,
 	size_t len;
 	char *pathname;
 
-	cfd = get_cgroup_fd(controller);
+	cfd = get_cgroup_fd_handle_named(controller);
 	if (cfd < 0)
 		return false;
 
@@ -1299,7 +1325,7 @@ static bool do_read_pids(pid_t tpid, const char *contrl, const char *cg,
 	struct ucred cred;
 	size_t sz = 0, asz = 0;
 
-	if (!cgroup_ops->get(cgroup_ops, contrl, cg, file, &tmpdata))
+	if (!get_cgroup_handle_named(cgroup_ops, contrl, cg, file, &tmpdata))
 		return false;
 
 	/*
@@ -1416,7 +1442,7 @@ __lxcfs_fuse_ops int cg_read(const char *path, char *buf, size_t size,
 		// special case - we have to translate the pids
 		r = do_read_pids(fc->pid, f->controller, f->cgroup, f->file, &data);
 	else
-		r = cgroup_ops->get(cgroup_ops, f->controller, f->cgroup, f->file, &data);
+		r = get_cgroup_handle_named(cgroup_ops, f->controller, f->cgroup, f->file, &data);
 
 	if (!r) {
 		ret = -EINVAL;
@@ -1513,7 +1539,7 @@ static FILE *open_pids_file(const char *controller, const char *cgroup)
 	size_t len;
 	char *pathname;
 
-	cfd = get_cgroup_fd(controller);
+	cfd = get_cgroup_fd_handle_named(controller);
 	if (cfd < 0)
 		return false;
 
@@ -1808,7 +1834,7 @@ static bool cgfs_set_value(const char *controller, const char *cgroup,
 	size_t len;
 	char *fnam;
 
-	cfd = get_cgroup_fd(controller);
+	cfd = get_cgroup_fd_handle_named(controller);
 	if (cfd < 0)
 		return false;
 
@@ -1894,7 +1920,7 @@ static bool cgfs_iterate_cgroup(const char *controller, const char *cgroup,
 	struct dirent *dirent;
 	DIR *dir;
 
-	cfd = get_cgroup_fd(controller);
+	cfd = get_cgroup_fd_handle_named(controller);
 	*list = NULL;
 	if (cfd < 0)
 		return false;
diff --git a/src/cgroups/cgfsng.c b/src/cgroups/cgfsng.c
index 98d8ca6..aba457b 100644
--- a/src/cgroups/cgfsng.c
+++ b/src/cgroups/cgfsng.c
@@ -500,7 +500,7 @@ static bool cgfsng_mount(struct cgroup_ops *ops, const char *root)
 					"Error creating cgroup path: %s",
 					controllerpath);
 
-		ret = cg_mount_cgroup_full( h, controllerpath);
+		ret = cg_mount_cgroup_full(h, controllerpath);
 		if (ret < 0)
 			goto on_error;
 	}
@@ -971,7 +971,7 @@ struct cgroup_ops *cgfsng_ops_init(void)
 	cgfsng_ops->num_hierarchies = cgfsng_num_hierarchies;
 	cgfsng_ops->get = cgfsng_get;
 	cgfsng_ops->get_hierarchies = cgfsng_get_hierarchies;
-	cgfsng_ops->get_hierarchy = get_hierarchy;
+	cgfsng_ops->get_hierarchy = cgfsng_get_hierarchy;
 	cgfsng_ops->driver = "cgfsng";
 	cgfsng_ops->version = "1.0.0";
 	cgfsng_ops->mount = cgfsng_mount;
diff --git a/src/cgroups/cgroup.h b/src/cgroups/cgroup.h
index dfcee0e..84049c7 100644
--- a/src/cgroups/cgroup.h
+++ b/src/cgroups/cgroup.h
@@ -17,6 +17,7 @@
 #include <stdbool.h>
 #include <stddef.h>
 #include <sys/types.h>
+#include <unistd.h>
 
 #include "../config.h"
 #include "../macro.h"
diff --git a/src/lxcfs.c b/src/lxcfs.c
index 44e7956..161907f 100644
--- a/src/lxcfs.c
+++ b/src/lxcfs.c
@@ -1058,9 +1058,16 @@ static int set_pidfile(char *pidfile)
 	return move_fd(fd);
 }
 
+static inline bool cgns_supported(void)
+{
+	return access("/proc/self/ns/cgroup", F_OK);
+}
+
 int main(int argc, char *argv[])
 {
 	__do_close_prot_errno int pidfile_fd = -EBADF;
+	char __default_opts[] = "default_permissions,allow_other,direct_io,entry_timeout=0.5,attr_timeout=0.5,nonempty";
+	char *default_opts = __default_opts;
 	int ret = EXIT_FAILURE;
 	char *pidfile = NULL, *saveptr = NULL, *token = NULL, *v = NULL;
 	char pidfile_buf[STRLITERALLEN(RUNTIME_PATH) + STRLITERALLEN("/lxcfs.pid") + 1] = {};
@@ -1159,10 +1166,20 @@ int main(int argc, char *argv[])
 	else
 		newargv[cnt++] = "-f";
 	newargv[cnt++] = "-o";
-	if (nonempty)
-		newargv[cnt++] = "default_permissions,allow_other,direct_io,entry_timeout=0.5,attr_timeout=0.5,nonempty";
-	else
-		newargv[cnt++] = "default_permissions,allow_other,direct_io,entry_timeout=0.5,attr_timeout=0.5";
+
+	if (!nonempty)
+		default_opts[STRARRAYLEN(__default_opts) - STRLITERALLEN("nonempty,")] = '\0';
+
+	/*
+	 * If cgroup namespaces are not supported lxcfs will need to supply
+	 * cgroup virtualization support. In this case we need custom access
+	 * permission checking and can't rely on fuse.
+	 */
+	if (!cgns_supported())
+		default_opts += STRLITERALLEN("default_permissions,");
+
+	newargv[cnt++] = default_opts;
+
 	newargv[cnt++] = argv[1];
 	newargv[cnt++] = NULL;
 
diff --git a/src/macro.h b/src/macro.h
index 29b5ed7..5d82509 100644
--- a/src/macro.h
+++ b/src/macro.h
@@ -67,6 +67,7 @@
 	})
 
 #define STRLITERALLEN(x) (sizeof(""x"") - 1)
+#define STRARRAYLEN(x) (sizeof(x) - 1)
 
 /* Calculate the number of chars needed to represent a given integer as a C
  * string. Include room for '-' to indicate negative numbers and the \0 byte.


More information about the lxc-devel mailing list