]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
cgfsng: reduce delta
authorChristian Brauner <christian.brauner@ubuntu.com>
Sat, 20 Jan 2018 11:52:08 +0000 (12:52 +0100)
committerChristian Brauner <christian.brauner@ubuntu.com>
Sat, 20 Jan 2018 11:52:08 +0000 (12:52 +0100)
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/cgroups/cgfsng.c

index 5fd576b2c04104b5db2936e95cdc7cddc9ae8003..0a2636ca8d81a06f9b5361542d0f545b0ef2330d 100644 (file)
@@ -54,8 +54,9 @@
 #include "cgroup.h"
 #include "cgroup_utils.h"
 #include "commands.h"
+#include "conf.h"
 #include "log.h"
-#include "storage.h"
+#include "storage/storage.h"
 #include "utils.h"
 
 lxc_log_define(lxc_cgfsng, lxc);
@@ -394,7 +395,7 @@ static ssize_t get_max_cpus(char *cpulist)
                c2 = c1;
        else if (c1 < c2)
                c1 = c2;
-       else if (!c1 && c2) // The reverse case is obvs. not needed.
+       else if (!c1 && c2) /* The reverse case is obvs. not needed. */
                c1 = c2;
 
        /* If the above logic is correct, c1 should always hold a valid string
@@ -422,7 +423,7 @@ static bool filter_and_set_cpus(char *path, bool am_initialized)
        bool bret = false, flipped_bit = false;
 
        lastslash = strrchr(path, '/');
-       if (!lastslash) { // bug...  this shouldn't be possible
+       if (!lastslash) { /* bug...  this shouldn't be possible */
                ERROR("Invalid path: %s.", path);
                return bret;
        }
@@ -555,7 +556,7 @@ static bool copy_parent_file(char *path, char *file)
        int ret;
 
        lastslash = strrchr(path, '/');
-       if (!lastslash) { // bug...  this shouldn't be possible
+       if (!lastslash) { /* bug...  this shouldn't be possible */
                ERROR("cgfsng:copy_parent_file: bad path %s", path);
                return false;
        }
@@ -992,8 +993,10 @@ static void lxc_cgfsng_print_handler_data(const struct cgfsng_handler_data *d)
        printf("Cgroup information:\n");
        printf("  container name: %s\n", d->name ? d->name : "(null)");
        printf("  lxc.cgroup.use: %s\n", cgroup_use ? cgroup_use : "(null)");
-       printf("  lxc.cgroup.pattern: %s\n", d->cgroup_pattern ? d->cgroup_pattern : "(null)");
-       printf("  cgroup: %s\n", d->container_cgroup ? d->container_cgroup : "(null)");
+       printf("  lxc.cgroup.pattern: %s\n",
+              d->cgroup_pattern ? d->cgroup_pattern : "(null)");
+       printf("  cgroup: %s\n",
+              d->container_cgroup ? d->container_cgroup : "(null)");
 }
 
 static void lxc_cgfsng_print_hierarchies()
@@ -1146,7 +1149,6 @@ static bool collect_hierarchy_info(void)
        const char *tmp;
        errno = 0;
        tmp = lxc_global_config_value("lxc.cgroup.use");
-
        if (!cgroup_use && errno != 0) { /* lxc.cgroup.use can be NULL */
                CGFSNG_DEBUG("Failed to retrieve list of cgroups to use\n");
                return false;
@@ -1156,18 +1158,21 @@ static bool collect_hierarchy_info(void)
        return parse_hierarchies();
 }
 
-static void *cgfsng_init(const char *name)
+static void *cgfsng_init(struct lxc_handler *handler)
 {
-       struct cgfsng_handler_data *d;
        const char *cgroup_pattern;
+       struct cgfsng_handler_data *d;
 
        d = must_alloc(sizeof(*d));
        memset(d, 0, sizeof(*d));
 
-       d->name = must_copy_string(name);
+       /* copy container name */
+       d->name = must_copy_string(handler->name);
 
+       /* copy system-wide cgroup information */
        cgroup_pattern = lxc_global_config_value("lxc.cgroup.pattern");
-       if (!cgroup_pattern) { // lxc.cgroup.pattern is only NULL on error
+       if (!cgroup_pattern) {
+               /* lxc.cgroup.pattern is only NULL on error. */
                ERROR("Error getting cgroup pattern");
                goto out_free;
        }
@@ -1332,7 +1337,7 @@ struct cgroup_ops *cgfsng_ops_init(void)
 static bool create_path_for_hierarchy(struct hierarchy *h, char *cgname)
 {
        h->fullcgpath = must_make_path(h->mountpoint, h->base_cgroup, cgname, NULL);
-       if (dir_exists(h->fullcgpath)) { // it must not already exist
+       if (dir_exists(h->fullcgpath)) { /* it must not already exist */
                ERROR("Path \"%s\" already existed.", h->fullcgpath);
                return false;
        }
@@ -1357,14 +1362,15 @@ static void remove_path_for_hierarchy(struct hierarchy *h, char *cgname)
  */
 static inline bool cgfsng_create(void *hdata)
 {
-       struct cgfsng_handler_data *d = hdata;
-       char *tmp, *cgname, *offset;
        int i;
-       int idx = 0;
        size_t len;
+       char *cgname, *offset, *tmp;
+       int idx = 0;
+       struct cgfsng_handler_data *d = hdata;
 
        if (!d)
                return false;
+
        if (d->container_cgroup) {
                WARN("cgfsng_create called a second time");
                return false;
@@ -1375,7 +1381,7 @@ static inline bool cgfsng_create(void *hdata)
                ERROR("Failed expanding cgroup name pattern");
                return false;
        }
-       len = strlen(tmp) + 5; // leave room for -NNN\0
+       len = strlen(tmp) + 5; /* leave room for -NNN\0 */
        cgname = must_alloc(len);
        strcpy(cgname, tmp);
        free(tmp);
@@ -1403,7 +1409,7 @@ again:
        for (i = 0; hierarchies[i]; i++) {
                if (!create_path_for_hierarchy(hierarchies[i], cgname)) {
                        int j;
-                       SYSERROR("Failed to create %s: %s", hierarchies[i]->fullcgpath, strerror(errno));
+                       ERROR("Failed to create \"%s\"", hierarchies[i]->fullcgpath);
                        free(hierarchies[i]->fullcgpath);
                        hierarchies[i]->fullcgpath = NULL;
                        for (j = 0; j < i; j++)
@@ -1444,11 +1450,6 @@ static bool cgfsng_enter(void *hdata, pid_t pid)
        return true;
 }
 
-struct chown_data {
-       struct cgfsng_handler_data *d;
-       uid_t origuid; // target uid in parent namespace
-};
-
 /*
  * chgrp the container cgroups to container group.  We leave
  * the container owner as cgroup owner.  So we must make the
@@ -1916,13 +1917,6 @@ static char *build_full_cgpath_from_monitorpath(struct hierarchy *h,
                                                const char *inpath,
                                                const char *filename)
 {
-       /*
-        * XXX Remove this case after 2.0 release.  It's for dealing with
-        * containers spawned under the old buggy cgfsng which wasn't around
-        * for long.
-        */
-       if (strncmp(inpath, "/sys/fs/cgroup/", 15) == 0)
-               return must_make_path(inpath, filename, NULL);
        return must_make_path(h->mountpoint, inpath, filename, NULL);
 }
 
@@ -1940,7 +1934,7 @@ static bool cgfsng_attach(const char *name, const char *lxcpath, pid_t pid)
                struct hierarchy *h = hierarchies[i];
 
                path = lxc_cmd_get_cgroup_path(name, lxcpath, h->controllers[0]);
-               if (!path) // not running
+               if (!path) /* not running */
                        continue;
 
                fullpath = build_full_cgpath_from_monitorpath(h, path, "cgroup.procs");
@@ -1973,7 +1967,7 @@ static int cgfsng_get(const char *filename, char *value, size_t len, const char
                *p = '\0';
 
        path = lxc_cmd_get_cgroup_path(name, lxcpath, subsystem);
-       if (!path) // not running
+       if (!path) /* not running */
                return -1;
 
        h = get_hierarchy(subsystem);
@@ -2005,7 +1999,7 @@ static int cgfsng_set(const char *filename, const char *value, const char *name,
                *p = '\0';
 
        path = lxc_cmd_get_cgroup_path(name, lxcpath, subsystem);
-       if (!path) // not running
+       if (!path) /* not running */
                return -1;
 
        h = get_hierarchy(subsystem);
@@ -2020,6 +2014,82 @@ static int cgfsng_set(const char *filename, const char *value, const char *name,
        return ret;
 }
 
+/*
+ * take devices cgroup line
+ *    /dev/foo rwx
+ * and convert it to a valid
+ *    type major:minor mode
+ * line.  Return <0 on error.  Dest is a preallocated buffer
+ * long enough to hold the output.
+ */
+static int convert_devpath(const char *invalue, char *dest)
+{
+       int n_parts;
+       char *p, *path, type;
+       struct stat sb;
+       unsigned long minor, major;
+       int ret = -EINVAL;
+       char *mode = NULL;
+
+       path = must_copy_string(invalue);
+
+       /*
+        * read path followed by mode;  ignore any trailing text.
+        * A '    # comment' would be legal.  Technically other text
+        * is not legal, we could check for that if we cared to
+        */
+       for (n_parts = 1, p = path; *p && n_parts < 3; p++) {
+               if (*p != ' ')
+                       continue;
+               *p = '\0';
+               if (n_parts != 1)
+                       break;
+               p++;
+               n_parts++;
+               while (*p == ' ')
+                       p++;
+               mode = p;
+               if (*p == '\0')
+                       goto out;
+       }
+
+       if (n_parts == 1)
+               goto out;
+
+       ret = stat(path, &sb);
+       if (ret < 0)
+               goto out;
+
+       mode_t m = sb.st_mode & S_IFMT;
+       switch (m) {
+       case S_IFBLK:
+               type = 'b';
+               break;
+       case S_IFCHR:
+               type = 'c';
+               break;
+       default:
+               ERROR("Unsupported device type %i for %s", m, path);
+               ret = -EINVAL;
+               goto out;
+       }
+
+       major = MAJOR(sb.st_rdev);
+       minor = MINOR(sb.st_rdev);
+       ret = snprintf(dest, 50, "%c %lu:%lu %s", type, major, minor, mode);
+       if (ret < 0 || ret >= 50) {
+               ERROR("Error on configuration value \"%c %lu:%lu %s\" (max 50 "
+                     "chars)", type, major, minor, mode);
+               ret = -ENAMETOOLONG;
+               goto out;
+       }
+       ret = 0;
+
+out:
+       free(path);
+       return ret;
+}
+
 /*
  * Called from setup_limits - here we have the container's cgroup_data because
  * we created the cgroups
@@ -2027,6 +2097,8 @@ static int cgfsng_set(const char *filename, const char *value, const char *name,
 static int lxc_cgroup_set_data(const char *filename, const char *value, struct cgfsng_handler_data *d)
 {
        char *fullpath, *p;
+       /* "b|c <2^64-1>:<2^64-1> r|w|m" = 47 chars max */
+       char converted_value[50];
        struct hierarchy *h;
        int ret = 0;
        char *controller = NULL;
@@ -2036,6 +2108,14 @@ static int lxc_cgroup_set_data(const char *filename, const char *value, struct c
        if ((p = strchr(controller, '.')) != NULL)
                *p = '\0';
 
+       if (strcmp("devices.allow", filename) == 0 && value[0] == '/') {
+               ret = convert_devpath(value, converted_value);
+               if (ret < 0)
+                       return ret;
+               value = converted_value;
+
+       }
+
        h = get_hierarchy(controller);
        if (!h) {
                ERROR("Failed to setup limits for the \"%s\" controller. "