int cg_create(const char *controller, const char *path, const char *suffix) { _cleanup_free_ char *fs = NULL; int r; #ifdef HAVE_CGMANAGER /* CGManager support */ int existed; if (cgm_dbus_connect()) { if (!controller) { cgm_dbus_disconnect(); return -1; } r = cgm_create(normalize_controller(controller), path, &existed); cgm_dbus_disconnect(); if (!r) return -1; return 1; } #endif r = cg_get_path_and_check(controller, path, suffix, &fs); if (r < 0) return r; r = mkdir_parents_label(fs, 0755); if (r < 0) return r; if (mkdir(fs, 0755) < 0) { if (errno == EEXIST) return 0; return -errno; } return 1; }
static int handle_login(const char *user) { int idx = 0, ret; int existed = 1; size_t ulen = strlen("user/") + strlen(user); size_t len = ulen + 50; // Just make sure there's room for "user/$user or an <integer>" uid_t uid = 0; gid_t gid = 0; nih_local char *cg = NIH_MUST( nih_alloc(NULL, len) ); if (!get_uid_gid(user, &uid, &gid)) { mysyslog(LOG_ERR, "failed to get uid and gid for %s\n", user); return PAM_SESSION_ERR; } memset(cg, 0, len); strcpy(cg, user); ret = snprintf(cg, len, "user/%s", user); if (ret < 0 || ret >= len) return PAM_SESSION_ERR; if (!cgm_create(cg, &existed)) { mysyslog(LOG_ERR, "failed to create cgroup %s\n", cg); return PAM_SESSION_ERR; } if (existed == 0) { if (!cgm_autoremove(cg)) { mysyslog(LOG_ERR, "Warning: failed to set autoremove on %s\n", cg); } } if (!cgm_enter(cg)) { mysyslog(LOG_ERR, "failed to enter cgroup %s\n", cg); return PAM_SESSION_ERR; } while (idx >= 0) { sprintf(cg, "%d", idx); if (!cgm_create(cg, &existed)) { mysyslog(LOG_ERR, "failed to create a user cgroup\n"); return PAM_SESSION_ERR; } if (existed == 1) { idx++; continue; } if (!cgm_chown(cg, uid, gid)) { mysyslog(LOG_ERR, "Warning: failed to chown %s\n", cg); } if (!cgm_autoremove(cg)) { mysyslog(LOG_ERR, "Warning: failed to set autoremove on %s\n", cg); } if (!cgm_enter(cg)) { mysyslog(LOG_ERR, "failed to enter user cgroup %s\n", cg); return PAM_SESSION_ERR; } break; } return PAM_SUCCESS; }