]> git.proxmox.com Git - mirror_lxcfs.git/commitdiff
Merge pull request #221 from brauner/2017-11-02/cgroup_v2_fixes
authorSerge Hallyn <serge@hallyn.com>
Sat, 11 Nov 2017 00:55:31 +0000 (18:55 -0600)
committerGitHub <noreply@github.com>
Sat, 11 Nov 2017 00:55:31 +0000 (18:55 -0600)
pam: cgroup v2 fixes

bindings.c
pam/pam_cgfs.c

index fe521a3317625bb0e7afddc935ed399f8368ad74..bde433cb50836da6bf581c56b565bfe0913e5ca6 100644 (file)
@@ -139,6 +139,7 @@ static char **hierarchies;
  * another namespace using the *at() family of functions
  * {openat(), fchownat(), ...}. */
 static int *fd_hierarchies;
+static int cgroup_mount_ns_fd = -1;
 
 static void unlock_mutex(pthread_mutex_t *l)
 {
@@ -421,6 +422,7 @@ static void print_subsystems(void)
 {
        int i;
 
+       fprintf(stderr, "mount namespace: %d\n", cgroup_mount_ns_fd);
        fprintf(stderr, "hierarchies:\n");
        for (i = 0; i < num_hierarchies; i++) {
                if (hierarchies[i])
@@ -3591,24 +3593,6 @@ static uint64_t get_reaper_age(pid_t pid)
        return procage;
 }
 
-static uint64_t get_reaper_btime(pid)
-{
-       int ret;
-       struct sysinfo sys;
-       uint64_t procstart;
-       uint64_t uptime;
-
-       ret = sysinfo(&sys);
-       if (ret < 0) {
-               lxcfs_debug("%s\n", "failed to retrieve system information");
-               return 0;
-       }
-
-       uptime = (uint64_t)time(NULL) - (uint64_t)sys.uptime;
-       procstart = get_reaper_start_time_in_sec(pid);
-       return uptime + procstart;
-}
-
 #define CPUALL_MAX_SIZE (BUF_RESERVE_SIZE / 2)
 static int proc_stat_read(char *buf, size_t size, off_t offset,
                struct fuse_file_info *fi)
@@ -4477,6 +4461,19 @@ static bool permute_root(void)
        return true;
 }
 
+static int preserve_mnt_ns(int pid)
+{
+       int ret;
+       size_t len = sizeof("/proc/") + 21 + sizeof("/ns/mnt");
+       char path[len];
+
+       ret = snprintf(path, len, "/proc/%d/ns/mnt", pid);
+       if (ret < 0 || (size_t)ret >= len)
+               return -1;
+
+       return open(path, O_RDONLY | O_CLOEXEC);
+}
+
 static bool cgfs_prepare_mounts(void)
 {
        if (!mkdir_p(BASEDIR, 0700)) {
@@ -4494,6 +4491,12 @@ static bool cgfs_prepare_mounts(void)
                return false;
        }
 
+       cgroup_mount_ns_fd = preserve_mnt_ns(getpid());
+       if (cgroup_mount_ns_fd < 0) {
+               lxcfs_error("Failed to preserve mount namespace: %s.\n", strerror(errno));
+               return false;
+       }
+
        if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, 0) < 0) {
                lxcfs_error("Failed to remount / private: %s.\n", strerror(errno));
                return false;
@@ -4567,19 +4570,6 @@ static bool cgfs_setup_controllers(void)
        return true;
 }
 
-static int preserve_ns(int pid)
-{
-       int ret;
-       size_t len = 5 /* /proc */ + 21 /* /int_as_str */ + 7 /* /ns/mnt */ + 1 /* \0 */;
-       char path[len];
-
-       ret = snprintf(path, len, "/proc/%d/ns/mnt", pid);
-       if (ret < 0 || (size_t)ret >= len)
-               return -1;
-
-       return open(path, O_RDONLY | O_CLOEXEC);
-}
-
 static void __attribute__((constructor)) collect_and_mount_subsystems(void)
 {
        FILE *f;
@@ -4623,7 +4613,7 @@ static void __attribute__((constructor)) collect_and_mount_subsystems(void)
        }
 
        /* Preserve initial namespace. */
-       init_ns = preserve_ns(getpid());
+       init_ns = preserve_mnt_ns(getpid());
        if (init_ns < 0) {
                lxcfs_error("%s\n", "Failed to preserve initial mount namespace.");
                goto out;
@@ -4680,4 +4670,7 @@ static void __attribute__((destructor)) free_subsystems(void)
        }
        free(hierarchies);
        free(fd_hierarchies);
+
+       if (cgroup_mount_ns_fd >= 0)
+               close(cgroup_mount_ns_fd);
 }
index ecd0618e640d6da4cddceeb8c1fab3118adf218d..1880352a2e8e2f19279719fa3c8f27534960d2f2 100644 (file)
@@ -2267,6 +2267,7 @@ static bool cgv1_create(const char *cgroup, uid_t uid, gid_t gid, bool *existed)
  */
 static bool cgv2_create(const char *cgroup, uid_t uid, gid_t gid, bool *existed)
 {
+       int ret;
        char *clean_base_cgroup;
        char *path;
        struct cgv2_hierarchy *v2;
@@ -2284,7 +2285,7 @@ static bool cgv2_create(const char *cgroup, uid_t uid, gid_t gid, bool *existed)
         */
        if (cg_systemd_chown_existing_cgroup(v2->mountpoint, v2->base_cgroup,
                                             uid, gid, v2->systemd_user_slice))
-               goto chown_cgroup_procs_file;
+               goto delegate_files;
 
        /* We need to make sure that we do not create an endless chain of
         * sub-cgroups. So we check if we have already logged in somehow (sudo
@@ -2310,7 +2311,7 @@ static bool cgv2_create(const char *cgroup, uid_t uid, gid_t gid, bool *existed)
                free(path);
                if (our_cg) {
                        *existed = false;
-                       goto chown_cgroup_procs_file;
+                       goto delegate_files;
                } else {
                        *existed = true;
                        return false;
@@ -2331,7 +2332,7 @@ static bool cgv2_create(const char *cgroup, uid_t uid, gid_t gid, bool *existed)
                lxcfs_debug("Chowned %s to %d:%d.\n", path, (int)uid, (int)gid);
        free(path);
 
-chown_cgroup_procs_file:
+delegate_files:
        /* chown cgroup.procs to user */
        if (v2->systemd_user_slice)
                path = must_make_path(v2->mountpoint, v2->base_cgroup,
@@ -2339,13 +2340,40 @@ chown_cgroup_procs_file:
        else
                path = must_make_path(v2->mountpoint, v2->base_cgroup, cgroup,
                                      "/cgroup.procs", NULL);
-       if (chown(path, uid, gid) < 0)
+       ret = chown(path, uid, gid);
+       if (ret < 0)
                mysyslog(LOG_WARNING, "Failed to chown %s to %d:%d: %s.\n",
                         path, (int)uid, (int)gid, strerror(errno), NULL);
        else
                lxcfs_debug("Chowned %s to %d:%d.\n", path, (int)uid, (int)gid);
        free(path);
 
+       /* chown cgroup.subtree_control to user */
+       if (v2->systemd_user_slice)
+               path = must_make_path(v2->mountpoint, v2->base_cgroup,
+                                     "/cgroup.subtree_control", NULL);
+       else
+               path = must_make_path(v2->mountpoint, v2->base_cgroup, cgroup,
+                                     "/cgroup.subtree_control", NULL);
+       ret = chown(path, uid, gid);
+       if (ret < 0)
+               mysyslog(LOG_WARNING, "Failed to chown %s to %d:%d: %s.\n",
+                        path, (int)uid, (int)gid, strerror(errno), NULL);
+       free(path);
+
+       /* chown cgroup.threads to user */
+       if (v2->systemd_user_slice)
+               path = must_make_path(v2->mountpoint, v2->base_cgroup,
+                                     "/cgroup.threads", NULL);
+       else
+               path = must_make_path(v2->mountpoint, v2->base_cgroup, cgroup,
+                                     "/cgroup.threads", NULL);
+       ret = chown(path, uid, gid);
+       if (ret < 0 && errno != ENOENT)
+               mysyslog(LOG_WARNING, "Failed to chown %s to %d:%d: %s.\n",
+                        path, (int)uid, (int)gid, strerror(errno), NULL);
+       free(path);
+
        return true;
 }