Add funbction to mount cgroup filesystem hierarchy into the container,
allowing only access to the parts that the container should have access
to, but none else.

Signed-off-by: Christian Seiler <christ...@iwakd.de>
---
 src/lxc/cgroup.c |  127 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/lxc/cgroup.h |    2 +
 2 files changed, 129 insertions(+)

diff --git a/src/lxc/cgroup.c b/src/lxc/cgroup.c
index ad95fc4..876c60c 100644
--- a/src/lxc/cgroup.c
+++ b/src/lxc/cgroup.c
@@ -34,6 +34,7 @@
 #include <sys/stat.h>
 #include <sys/param.h>
 #include <sys/inotify.h>
+#include <sys/mount.h>
 #include <netinet/in.h>
 #include <net/if.h>
 
@@ -1200,6 +1201,132 @@ int lxc_setup_cgroup_devices(struct lxc_handler *h, 
struct lxc_list *cgroup_sett
        return do_setup_cgroup(h, cgroup_settings, true);
 }
 
+int lxc_setup_mount_cgroup(const char *root, struct cgroup_process_info 
*base_info)
+{
+       size_t bufsz = strlen(root) + sizeof("/sys/fs/cgroup");
+       char *path = NULL;
+       char **parts = NULL;
+       char *dirname = NULL;
+       char *abs_path = NULL;
+       char *abs_path2 = NULL;
+       struct cgroup_process_info *info;
+       int r, saved_errno = 0;
+
+       path = calloc(1, bufsz);
+       if (!path)
+               return -1;
+       snprintf(path, bufsz, "%s/sys/fs/cgroup", root);
+       r = mount("cgroup_root", path, "tmpfs", 
MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_RELATIME, "size=10240k,mode=755");
+       if (r < 0) {
+               SYSERROR("could not mount tmpfs to /sys/fs/cgroup in the 
container");
+               return -1;
+       }
+
+       /* now mount all the hierarchies we care about */
+       for (info = base_info; info; info = info->next) {
+               size_t subsystem_count, i;
+               struct cgroup_mount_point *mp = info->designated_mount_point;
+               if (!mp)
+                       mp = lxc_cgroup_find_mount_point(info->hierarchy, 
info->cgroup_path, true);
+               if (!mp) {
+                       SYSERROR("could not find original mount point for 
cgroup hierarchy while trying to mount cgroup filesystem");
+                       goto out_error;
+               }
+
+               subsystem_count = lxc_array_len((void 
**)info->hierarchy->subsystems);
+               parts = calloc(subsystem_count + 1, sizeof(char *));
+               if (!parts)
+                       goto out_error;
+
+               for (i = 0; i < subsystem_count; i++) {
+                       if (!strncmp(info->hierarchy->subsystems[i], "name=", 
5))
+                               parts[i] = info->hierarchy->subsystems[i] + 5;
+                       else
+                               parts[i] = info->hierarchy->subsystems[i];
+               }
+               dirname = lxc_string_join(",", (const char **)parts, false);
+               if (!dirname)
+                       goto out_error;
+
+               /* create subsystem directory */
+               abs_path = lxc_append_paths(path, dirname);
+               if (!abs_path)
+                       goto out_error;
+               r = mkdir_p(abs_path, 0755);
+               if (r < 0 && errno != EEXIST) {
+                       SYSERROR("could not create cgroup subsystem directory 
/sys/fs/cgroup/%s", dirname);
+                       goto out_error;
+               }
+
+               /* create path for container's cgroup */
+               abs_path2 = lxc_append_paths(abs_path, info->cgroup_path);
+               if (!abs_path2)
+                       goto out_error;
+               r = mkdir_p(abs_path2, 0755);
+               if (r < 0 && errno != EEXIST) {
+                       SYSERROR("could not create cgroup directory 
/sys/fs/cgroup/%s%s", dirname, info->cgroup_path);
+                       goto out_error;
+               }
+
+               free(abs_path);
+               abs_path = NULL;
+
+               /* bind-mount container's cgroup to that directory */
+               abs_path = cgroup_to_absolute_path(mp, info->cgroup_path, NULL);
+               if (!abs_path)
+                       goto out_error;
+               r = mount(abs_path, abs_path2, "none", MS_BIND, 0);
+               if (r < 0) {
+                       SYSERROR("error bind-mounting %s to %s", abs_path, 
abs_path2);
+                       goto out_error;
+               }
+
+               free(abs_path);
+               free(abs_path2);
+               abs_path = NULL;
+               abs_path2 = NULL;
+
+               /* add symlinks for every single subsystem */
+               if (subsystem_count > 1) {
+                       for (i = 0; i < subsystem_count; i++) {
+                               abs_path = lxc_append_paths(path, parts[i]);
+                               if (!abs_path)
+                                       goto out_error;
+                               r = symlink(dirname, abs_path);
+                               if (r < 0)
+                                       WARN("could not create symlink %s -> %s 
in /sys/fs/cgroup of container", parts[i], dirname);
+                               free(abs_path);
+                               abs_path = NULL;
+                       }
+               }
+               free(dirname);
+               free(parts);
+               dirname = NULL;
+               parts = NULL;
+       }
+
+       /* try to remount the tmpfs readonly, since the container shouldn't
+        * change anything (this will also make sure that trying to create
+        * new cgroups outside the allowed area fails with an error instead
+        * of simply causing this to create directories in the tmpfs itself)
+        */
+       mount(NULL, path, NULL, MS_REMOUNT|MS_RDONLY, NULL);
+
+       free(path);
+
+       return 0;
+
+out_error:
+       saved_errno = errno;
+       free(path);
+       free(dirname);
+       free(parts);
+       free(abs_path);
+       free(abs_path2);
+       errno = saved_errno;
+       return -1;
+}
+
 int lxc_cgroup_nrtasks_handler(struct lxc_handler *handler)
 {
        struct cgroup_process_info *info = handler->cgroup;
diff --git a/src/lxc/cgroup.h b/src/lxc/cgroup.h
index 2555390..ad9d596 100644
--- a/src/lxc/cgroup.h
+++ b/src/lxc/cgroup.h
@@ -160,6 +160,8 @@ struct lxc_list;
 extern int lxc_setup_cgroup_without_devices(struct lxc_handler *h, struct 
lxc_list *cgroup_settings);
 extern int lxc_setup_cgroup_devices(struct lxc_handler *h, struct lxc_list 
*cgroup_settings);
 
+extern int lxc_setup_mount_cgroup(const char *root, struct cgroup_process_info 
*base_info);
+
 extern int lxc_cgroup_nrtasks_handler(struct lxc_handler *handler);
 
 #endif
-- 
1.7.10.4


------------------------------------------------------------------------------
How ServiceNow helps IT people transform IT departments:
1. Consolidate legacy IT systems to a single system of record for IT
2. Standardize and globalize service processes across IT
3. Implement zero-touch automation to replace manual, redundant tasks
http://pubads.g.doubleclick.net/gampad/clk?id=51271111&iu=/4140/ostg.clktrk
_______________________________________________
Lxc-devel mailing list
Lxc-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/lxc-devel

Reply via email to