The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxcfs/pull/81
This e-mail was sent by the LXC bot, direct replies will not reach the author unless they happen to be subscribed to this list. === Description (from pull-request) === Don't always ignore it. Do ignore it (like all others) if not listed in the -c argument. If the logged in task's name=systemd cgroup != that of the init task's, assume we are in systemd and rename the user's. If they are the same, assume we are in upstart or sysvinit and create=chown a name=systemd cgroup just as for the others. This should fix https://bugs.launchpad.net/ubuntu/+source/lxcfs/+bug/1543353 and allow the ubuntu systemd package to drop its cgroup related delta. Signed-off-by: Serge Hallyn <serge.hal...@ubuntu.com>
From edd25678d5701cda14c36a511c4d01c53ebd9fd4 Mon Sep 17 00:00:00 2001 From: Serge Hallyn <serge.hal...@ubuntu.com> Date: Mon, 8 Feb 2016 21:58:11 -0800 Subject: [PATCH] pam_cgfs: change handling of name=systemd Don't always ignore it. Do ignore it (like all others) if not listed in the -c argument. If the logged in task's name=systemd cgroup != that of the init task's, assume we are in systemd and rename the user's. If they are the same, assume we are in upstart or sysvinit and create=chown a name=systemd cgroup just as for the others. This should fix https://bugs.launchpad.net/ubuntu/+source/lxcfs/+bug/1543353 and allow the ubuntu systemd package to drop its cgroup related delta. Signed-off-by: Serge Hallyn <serge.hal...@ubuntu.com> --- pam/pam_cgfs.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 69 insertions(+), 16 deletions(-) diff --git a/pam/pam_cgfs.c b/pam/pam_cgfs.c index 070aaf3..14581cb 100644 --- a/pam/pam_cgfs.c +++ b/pam/pam_cgfs.c @@ -3,14 +3,19 @@ * Copyright © 2016 Canonical, Inc * Author: Serge Hallyn <serge.hal...@ubuntu.com> * - * When a user logs in, this pam module will create cgroups which - * the user may administer, for all controllers except name=systemd, - * or for any controllers listed on the command line (if any are - * listed). + * When a user logs in, this pam module will create cgroups which the user + * may administer, either for all controllers or for any controllers listed + * on the command line (if any are listed). * * The cgroup created will be "user/$user/0" for the first session, * "user/$user/1" for the second, etc. * + * name=systemd is handled specially. If the host is an upstart system, + * the logged in user may not get a cgroup created. On a systemd system, + * one is created but not chowned to the user. In the former case, we + * create one as usual, in the latter case we simply chown whatever cgroup + * the user is in. + * * All requested cgroups must be mounted under /sys/fs/cgroup/$controller, * no messing around with finding mountpoints. * @@ -140,9 +145,11 @@ static bool mkdir_p(const char *root, char *path) struct controller { struct controller *next; int id; + bool systemd_created; char *name; char *mount_path; char *init_path; + char *cur_path; }; #define MAXCONTROLLERS 20 @@ -159,6 +166,12 @@ static char *find_controller_path(struct controller *c) if (exists(path)) return path; free(path); + if (strncmp(c->name, "name=", 5) == 0) { + path = must_strcat("/sys/fs/cgroup/", c->name + 5, NULL); + if (exists(path)) + return path; + free(path); + } c = c->next; } return NULL; @@ -185,7 +198,7 @@ static void get_mounted_paths(void) } } -static void add_controller(int id, char *tok) +static void add_controller(int id, char *tok, char *cur_path) { struct controller *c; @@ -195,6 +208,9 @@ static void add_controller(int id, char *tok) do { c->name = strdup(tok); } while (!c->name); + do { + c->cur_path = strdup(cur_path); + } while (!c->cur_path); c->id = id; c->next = controllers[id]; c->mount_path = NULL; @@ -213,6 +229,7 @@ static void drop_controller(int which) while (c) { struct controller *tmp = c->next; free(c->name); + free(c->cur_path); free(c); c = tmp; } @@ -309,8 +326,11 @@ static bool fill_in_init_paths(void) goto out; } prune_init_scope(ip); - for (c = controllers[id]; c; c = c->next) + for (c = controllers[id]; c; c = c->next) { + if (strcmp(c->name, "name=systemd") == 0) + c->systemd_created = strcmp(ip, c->cur_path) != 0; c->init_path = ip; + } } ret = true; out: @@ -335,6 +355,7 @@ static void print_found_controllers(void) { fprintf(stderr, " Next mount: index %d name %s\n", c->id, c->name); fprintf(stderr, " mount path %s\n", c->mount_path ? c->mount_path : "(none)"); fprintf(stderr, " init task path %s\n", c->init_path); + fprintf(stderr, " login task path %s\n", c->cur_path); c = c->next; } } @@ -350,7 +371,7 @@ static inline void print_found_controllers(void) { }; static bool get_active_controllers(void) { FILE *f; - char *line = NULL, *tok; + char *line = NULL, *tok, *cur_path; size_t len = 0; f = fopen("/proc/self/cgroup", "r"); @@ -359,7 +380,7 @@ static bool get_active_controllers(void) while (getline(&line, &len, f) != -1) { int id; char *subsystems; - if (sscanf(line, "%d:%m[^:]:", &id, &subsystems) != 2) { + if (sscanf(line, "%d:%m[^:]:%ms", &id, &subsystems, &cur_path) != 3) { mysyslog(LOG_ERR, "Corrupt /proc/self/cgroup\n"); fclose(f); free(line); @@ -368,16 +389,15 @@ static bool get_active_controllers(void) if (id < 0 || id > 20) { mysyslog(LOG_ERR, "Too many subsystems\n"); free(subsystems); + free(cur_path); fclose(f); free(line); return false; } - if (strcmp(subsystems, "name=systemd") == 0) - goto next; for (tok = strtok(subsystems, ","); tok; tok = strtok(NULL, ",")) - add_controller(id, tok); -next: + add_controller(id, tok, cur_path); free(subsystems); + free(cur_path); } fclose(f); free(line); @@ -396,11 +416,36 @@ static bool get_active_controllers(void) return true; } +/* + * Handle systemd creation. Return true if all's done. Returns false if + * the caller needs to create=chown a cgroup + */ +static bool handle_systemd_create(const struct controller *c, uid_t uid, gid_t gid) +{ + char *user_path; + + if (!c->systemd_created) + return false; + + user_path = must_strcat(c->mount_path, c->cur_path, NULL); + + // a name=systemd cgroup has already been created, just chown it + if (chown(user_path, uid, gid) < 0) + mysyslog(LOG_WARNING, "Failed to chown %s to %d:%d: %m\n", + user_path, (int)uid, (int)gid); + free(user_path); + return true; +} + static bool cgfs_create_forone(const struct controller *c, uid_t uid, gid_t gid, const char *cg, bool *existed) { while (c) { if (!c->mount_path || !c->init_path) goto next; + + if (strcmp(c->name, "name=systemd") == 0 && handle_systemd_create(c, uid, gid)) + return true; + char *path = must_strcat(c->mount_path, c->init_path, cg, NULL); #if DEBUG fprintf(stderr, "Creating %s for %s\n", path, c->name); @@ -409,10 +454,11 @@ static bool cgfs_create_forone(const struct controller *c, uid_t uid, gid_t gid, free(path); *existed = true; #if DEBUG - fprintf(stderr, "%s existed\n", path); + fprintf(stderr, "%s existed\n", path); #endif return true; } + bool pass = mkdir_p(c->mount_path, path); #if DEBUG fprintf(stderr, "Creating %s %s\n", path, pass ? "succeeded" : "failed"); @@ -551,7 +597,7 @@ static bool do_enter(struct controller *c, const char *cg) return false; } -static bool cgfs_enter(const char *cg) +static bool cgfs_enter(const char *cg, bool skip_systemd) { int i; @@ -561,6 +607,13 @@ static bool cgfs_enter(const char *cg) if (!c) continue; + if (strcmp(c->name, "name=systemd") == 0) { + if (skip_systemd) + continue; + if (c->systemd_created) + continue; + } + if (!do_enter(c, cg)) return false; } @@ -570,7 +623,7 @@ static bool cgfs_enter(const char *cg) static void cgfs_escape(void) { - if (!cgfs_enter("/")) { + if (!cgfs_enter("/", true)) { mysyslog(LOG_WARNING, "Failed to escape to init's cgroup\n"); } } @@ -621,7 +674,7 @@ static int handle_login(const char *user) continue; } - if (!cgfs_enter(cg)) { + if (!cgfs_enter(cg, false)) { mysyslog(LOG_ERR, "Failed to enter user cgroup %s for user %s\n", cg, user); return PAM_SESSION_ERR; }
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel