* See COPYING file for details.
*/
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
+#include <linux/unistd.h>
#include <pwd.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <syslog.h>
-#include <unistd.h>
-#include <linux/unistd.h>
#include <sys/mount.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/vfs.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include "config.h"
+#include "macro.h"
+#include "utils.h"
#define PAM_SM_SESSION
#include <security/_pam_macros.h>
#include <security/pam_modules.h>
-#include "utils.h"
+#ifndef HAVE_STRLCPY
+#include "include/strlcpy.h"
+#endif
+
+#ifndef HAVE_STRLCAT
+#include "include/strlcat.h"
+#endif
#define pam_cgfs_debug_stream(stream, format, ...) \
do { \
static bool is_lxcfs(const char *line);
static bool is_cgv1(char *line);
static bool is_cgv2(char *line);
-static void *must_alloc(size_t sz);
static void must_add_to_list(char ***clist, char *entry);
static void must_append_controller(char **klist, char **nlist, char ***clist,
char *entry);
static void must_append_string(char ***list, char *entry);
static void mysyslog(int err, const char *format, ...) __attribute__((sentinel));
static char *read_file(char *fnam);
-static int read_from_file(const char *filename, void* buf, size_t count);
static int recursive_rmdir(char *dirname);
static inline void set_bit(unsigned bit, uint32_t *bitarr)
{
static char *string_join(const char *sep, const char **parts, bool use_as_prefix);
static void trim(char *s);
static bool write_int(char *path, int v);
-static ssize_t write_nointr(int fd, const void* buf, size_t count);
-static int write_to_file(const char *filename, const void *buf, size_t count,
- bool add_newline);
/* cgroupfs prototypes. */
static bool cg_belongs_to_uid_gid(const char *path, uid_t uid, gid_t gid);
static bool cgv2_remove(const char *cgroup);
static bool is_cgv2(char *line);
+static int do_mkdir(const char *path, mode_t mode)
+{
+ int saved_errno;
+ mode_t mask;
+ int r;
+
+ mask = umask(0);
+ r = mkdir(path, mode);
+ saved_errno = errno;
+ umask(mask);
+ errno = saved_errno;
+ return (r);
+}
+
/* Create directory and (if necessary) its parents. */
static bool mkdir_parent(const char *root, char *path)
{
if (file_exists(path))
goto next;
- if (mkdir(path, 0755) < 0) {
- pam_cgfs_debug("Failed to create %s: %s.\n", path, strerror(errno));
+ if (do_mkdir(path, 0755) < 0) {
+ pam_cgfs_debug("Failed to create %s: %s\n", path, strerror(errno));
return false;
}
int newentry = 0;
if (*list)
- for (; (*list)[newentry]; newentry++) {
+ for (; (*list)[newentry]; newentry++)
;
- }
*list = must_realloc(*list, (newentry + 2) * sizeof(void **));
(*list)[newentry + 1] = NULL;
s[--len] = '\0';
}
-/* Allocate pointer; do not fail. */
-static void *must_alloc(size_t sz)
-{
- return must_realloc(NULL, sz);
-}
-
/* Make allocated copy of string. End of string is taken to be '\n'. */
static char *copy_to_eol(char *s)
{
return NULL;
len = newline - s;
- sret = must_alloc(len + 1);
+ sret = must_realloc(NULL, len + 1);
memcpy(sret, s, len);
sret[len] = '\0';
struct stat st;
char *pathname;
- if (!direntp)
- break;
-
if (!strcmp(direntp->d_name, ".") ||
!strcmp(direntp->d_name, ".."))
continue;
if (lstat(pathname, &st)) {
if (!r)
- pam_cgfs_debug("Failed to stat %s.\n", pathname);
+ pam_cgfs_debug("Failed to stat %s\n", pathname);
r = -1;
goto next;
}
if (recursive_rmdir(pathname) < 0)
r = -1;
+
next:
free(pathname);
}
if (rmdir(dirname) < 0) {
if (!r)
- pam_cgfs_debug("Failed to delete %s: %s.\n", dirname, strerror(errno));
+ pam_cgfs_debug("Failed to delete %s: %s\n", dirname, strerror(errno));
r = -1;
}
if (closedir(dir) < 0) {
if (!r)
- pam_cgfs_debug("Failed to delete %s: %s.\n", dirname, strerror(errno));
+ pam_cgfs_debug("Failed to delete %s: %s\n", dirname, strerror(errno));
r = -1;
}
*p2 = '\0';
len = strlen(p);
- sret = must_alloc(len + 1);
+ sret = must_realloc(NULL, len + 1);
memcpy(sret, p, len);
sret[len] = '\0';
if ((*it)->controllers)
if (cgv1_controller_lists_intersect((*it)->controllers, clist))
return true;
+
return false;
}
for (it = cgv1_hierarchies; it && *it; it++)
if ((*it)->controllers)
if (cgv1_controller_lists_intersect((*it)->controllers, clist) ||
- string_in_list(clist, "all"))
+ string_in_list(clist, "all"))
(*it)->create_rw_cgroup = true;
}
size_t len;
len = strlen(entry);
- s = must_alloc(len + 6);
+ s = must_realloc(NULL, len + 6);
ret = snprintf(s, len + 6, "name=%s", entry);
- if (ret < 0 || (size_t)ret >= (len + 6))
+ if (ret < 0 || (size_t)ret >= (len + 6)) {
+ free(s);
return NULL;
+ }
return s;
}
return NULL;
p++;
}
- if (!p)
- return NULL;
if (strncmp(p, "/sys/fs/cgroup/", 15) != 0)
return NULL;
if (strcmp(tok, c) == 0)
return true;
}
+
return false;
}
struct cgv1_hierarchy *new;
int newentry;
- new = must_alloc(sizeof(*new));
+ new = must_realloc(NULL, sizeof(*new));
+
new->controllers = clist;
new->mountpoint = mountpoint;
new->base_cgroup = base_cgroup;
struct cgv2_hierarchy *new;
int newentry;
- new = must_alloc(sizeof(*new));
+ new = must_realloc(NULL, sizeof(*new));
+
new->controllers = clist;
new->mountpoint = mountpoint;
new->base_cgroup = base_cgroup;
p--;
if (p < copy)
goto cleanup;
+
/* make sure it is something.session */
len = strlen(p + 1);
if (len < strlen("1.session") ||
*(p + 1) = '\0';
while (p >= copy && *(--p) != '/')
;
+
if (sscanf(p + 1, "%d.user/", &id) != 1)
goto cleanup;
succeed:
bret = true;
+
cleanup:
free(copy);
return bret;
* need to chown it.
*/
if (chown(path, uid, gid) < 0)
- mysyslog(LOG_WARNING, "Failed to chown %s to %d:%d: %s.\n",
- path, (int)uid, (int)gid, strerror(errno), NULL);
- pam_cgfs_debug("Chowned %s to %d:%d.\n", path, (int)uid, (int)gid);
+ mysyslog(LOG_WARNING, "Failed to chown %s to %d:%d: %s\n",
+ path, (int)uid, (int)gid, strerror(errno), NULL);
+ pam_cgfs_debug("Chowned %s to %d:%d\n", path, (int)uid, (int)gid);
free(path);
return true;
if (!controller_list)
continue;
- if (cgv1_controller_list_is_dup(cgv1_hierarchies,
- controller_list)) {
+ if (cgv1_controller_list_is_dup(cgv1_hierarchies, controller_list)) {
free(controller_list);
continue;
}
free(mountpoint);
continue;
}
+
trim(base_cgroup);
pam_cgfs_debug("Detected cgroupfs v1 controller \"%s\" with "
- "mountpoint \"%s\" and cgroup \"%s\".\n",
- controller_list[0], mountpoint, base_cgroup);
- cgv1_add_controller(controller_list, mountpoint, base_cgroup,
- NULL);
+ "mountpoint \"%s\" and cgroup \"%s\"\n",
+ controller_list[0], mountpoint, base_cgroup);
+ cgv1_add_controller(controller_list, mountpoint, base_cgroup, NULL);
}
+
free_string_list(klist);
free_string_list(nlist);
free(basecginfo);
for (it = cgv1_hierarchies; it && *it; it++) {
if ((*it)->controllers) {
char *init_cgroup, *user_slice;
+
/* We've already stored the controller and received its
* current cgroup. If we now fail to retrieve its init
* cgroup, we should probably fail.
free(basecginfo);
return false;
}
+
cg_systemd_prune_init_scope(init_cgroup);
(*it)->init_cgroup = init_cgroup;
pam_cgfs_debug("cgroupfs v1 controller \"%s\" has init "
- "cgroup \"%s\".\n",
- (*(*it)->controllers), init_cgroup);
+ "cgroup \"%s\"\n",
+ (*(*it)->controllers), init_cgroup);
+
/* Check whether systemd has already created a cgroup
* for us.
*/
user_slice = must_make_path((*it)->mountpoint, (*it)->base_cgroup, NULL);
if (cg_systemd_created_user_slice((*it)->base_cgroup, (*it)->init_cgroup, user_slice, uid))
(*it)->systemd_user_slice = true;
+
+ free(user_slice);
}
}
free(basecginfo);
}
/* Detect and store information about the cgroupfs v2 hierarchy. Currently only
- * deals with the empty v2 hierachy as we do not retrieve enabled controllers.
+ * deals with the empty v2 hierarchy as we do not retrieve enabled controllers.
*/
static bool cgv2_init(uid_t uid, gid_t gid)
{
*/
goto cleanup;
}
+
cg_systemd_prune_init_scope(init_cgroup);
/* Check if the v2 hierarchy is mounted at its standard location.
while (getline(&line, &len, f) != -1) {
char *user_slice;
bool has_user_slice = false;
+
if (!is_cgv2(line))
continue;
free(user_slice);
cgv2_add_controller(NULL, mountpoint, current_cgroup, init_cgroup, has_user_slice);
+
/* Although the unified hierarchy can be mounted multiple times,
* each of those mountpoints will expose identical information.
* So let the first mountpoint we find, win.
}
pam_cgfs_debug("Detected cgroupfs v2 hierarchy at mountpoint \"%s\" with "
- "current cgroup \"%s\" and init cgroup \"%s\".\n",
- mountpoint, current_cgroup, init_cgroup);
+ "current cgroup \"%s\" and init cgroup \"%s\"\n",
+ mountpoint, current_cgroup, init_cgroup);
cleanup:
if (f)
fclose(f);
free(line);
+ if (!ret) {
+ free(init_cgroup);
+ free(current_cgroup);
+ }
+
return ret;
}
if (cgv1_hierarchies && cgv2_hierarchies) {
cg_mount_mode = CGROUP_MIXED;
- pam_cgfs_debug("%s\n", "Detected cgroupfs v1 and v2 hierarchies.");
+ pam_cgfs_debug("%s\n", "Detected cgroupfs v1 and v2 hierarchies");
} else if (cgv1_hierarchies && !cgv2_hierarchies) {
cg_mount_mode = CGROUP_PURE_V1;
- pam_cgfs_debug("%s\n", "Detected cgroupfs v1 hierarchies.");
+ pam_cgfs_debug("%s\n", "Detected cgroupfs v1 hierarchies");
} else if (cgv2_hierarchies && !cgv1_hierarchies) {
cg_mount_mode = CGROUP_PURE_V2;
- pam_cgfs_debug("%s\n", "Detected cgroupfs v2 hierarchies.");
+ pam_cgfs_debug("%s\n", "Detected cgroupfs v2 hierarchies");
} else {
cg_mount_mode = CGROUP_UNKNOWN;
- mysyslog(LOG_ERR, "Could not detect cgroupfs hierarchy.\n", NULL);
+ mysyslog(LOG_ERR, "Could not detect cgroupfs hierarchy\n", NULL);
}
if (cg_mount_mode == CGROUP_UNKNOWN)
"/tasks",
NULL);
}
- pam_cgfs_debug("Attempting to enter cgroupfs v1 hierarchy in \"%s\" cgroup.\n", path);
+
+ pam_cgfs_debug("Attempting to enter cgroupfs v1 hierarchy in \"%s\" cgroup\n", path);
entered = write_int(path, (int)getpid());
if (entered) {
free(path);
break;
}
- pam_cgfs_debug("Failed to enter cgroupfs v1 hierarchy in \"%s\" cgroup.\n", path);
+
+ pam_cgfs_debug("Failed to enter cgroupfs v1 hierarchy in \"%s\" cgroup\n", path);
free(path);
}
+
if (!entered)
return false;
}
return true;
path = must_make_path(v2->mountpoint, v2->base_cgroup, cgroup, "/cgroup.procs", NULL);
- pam_cgfs_debug("Attempting to enter cgroupfs v2 hierarchy in cgroup \"%s\".\n", path);
+ pam_cgfs_debug("Attempting to enter cgroupfs v2 hierarchy in cgroup \"%s\"\n", path);
+
entered = write_int(path, (int)getpid());
if (!entered) {
- pam_cgfs_debug("Failed to enter cgroupfs v2 hierarchy in cgroup \"%s\".\n", path);
+ pam_cgfs_debug("Failed to enter cgroupfs v2 hierarchy in cgroup \"%s\"\n", path);
free(path);
return false;
}
static bool cg_enter(const char *cgroup)
{
if (!cgv1_enter(cgroup)) {
- mysyslog(LOG_WARNING, "cgroupfs v1: Failed to enter cgroups.\n", NULL);
+ mysyslog(LOG_WARNING, "cgroupfs v1: Failed to enter cgroups\n", NULL);
return false;
}
if (!cgv2_enter(cgroup)) {
- mysyslog(LOG_WARNING, "cgroupfs v2: Failed to enter cgroups.\n", NULL);
+ mysyslog(LOG_WARNING, "cgroupfs v2: Failed to enter cgroups\n", NULL);
return false;
}
*/
for (it = cgv1_hierarchies; it && *it; it++)
if (!cgv1_handle_root_cpuset_hierarchy(*it))
- mysyslog(LOG_WARNING, "cgroupfs v1: Failed to initialize cpuset.\n", NULL);
+ mysyslog(LOG_WARNING, "cgroupfs v1: Failed to initialize cpuset\n", NULL);
if (!cgv1_enter("/"))
- mysyslog(LOG_WARNING, "cgroupfs v1: Failed to escape to init's cgroup.\n", NULL);
+ mysyslog(LOG_WARNING, "cgroupfs v1: Failed to escape to init's cgroup\n", NULL);
}
/* Escape to root cgroup in the cgroupfs v2 hierarchy. */
static void cgv2_escape(void)
{
if (!cgv2_enter("/"))
- mysyslog(LOG_WARNING, "cgroupfs v2: Failed to escape to init's cgroup.\n", NULL);
+ mysyslog(LOG_WARNING, "cgroupfs v2: Failed to escape to init's cgroup\n", NULL);
}
/* Wrapper around cgv{1,2}_escape(). */
/* Get uid and gid for @user. */
static bool get_uid_gid(const char *user, uid_t *uid, gid_t *gid)
{
- struct passwd *pwent;
+ struct passwd pwent;
+ struct passwd *pwentp = NULL;
+ char *buf;
+ size_t bufsize;
+ int ret;
+
+ bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
+ if (bufsize == -1)
+ bufsize = 1024;
+
+ buf = malloc(bufsize);
+ if (!buf)
+ return false;
+
+ ret = getpwnam_r(user, &pwent, buf, bufsize, &pwentp);
+ if (!pwentp) {
+ if (ret == 0)
+ mysyslog(LOG_ERR,
+ "Could not find matched password record\n", NULL);
- pwent = getpwnam(user);
- if (!pwent)
+ free(buf);
return false;
+ }
- *uid = pwent->pw_uid;
- *gid = pwent->pw_gid;
+ *uid = pwent.pw_uid;
+ *gid = pwent.pw_gid;
+ free(buf);
return true;
}
char *range = strchr(token, '-');
if (range)
end = strtoul(range + 1, NULL, 0);
+
if (!(start <= end)) {
free(bitarr);
return NULL;
char **p;
size_t sep_len = strlen(sep);
size_t result_len = use_as_prefix * sep_len;
+ size_t buf_len;
if (!parts)
return NULL;
for (p = (char **)parts; *p; p++)
result_len += (p > (char **)parts) * sep_len + strlen(*p);
- result = calloc(result_len + 1, sizeof(char));
+ buf_len = result_len + 1;
+ result = calloc(buf_len, sizeof(char));
if (!result)
return NULL;
if (use_as_prefix)
- strcpy(result, sep);
+ (void)strlcpy(result, sep, buf_len * sizeof(char));
+
for (p = (char **)parts; *p; p++) {
if (p > (char **)parts)
- strcat(result, sep);
- strcat(result, *p);
+ (void)strlcat(result, sep, buf_len * sizeof(char));
+
+ (void)strlcat(result, *p, buf_len * sizeof(char));
}
return result;
free_string_list(cpulist);
return NULL;
}
+
must_append_string(&cpulist, numstr);
}
}
+
return string_join(",", (const char **)cpulist, false);
}
else if (c1 < c2)
c1 = c2;
+ if (!c1)
+ return -1;
+
/* If the above logic is correct, c1 should always hold a valid string
* here.
*/
-
errno = 0;
cpus = strtoul(c1, NULL, 0);
if (errno != 0)
return cpus;
}
-static ssize_t write_nointr(int fd, const void* buf, size_t count)
-{
- ssize_t ret;
-again:
- ret = write(fd, buf, count);
- if (ret < 0 && errno == EINTR)
- goto again;
- return ret;
-}
-
-static int write_to_file(const char *filename, const void* buf, size_t count, bool add_newline)
-{
- int fd, saved_errno;
- ssize_t ret;
-
- fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, 0666);
- if (fd < 0)
- return -1;
- ret = write_nointr(fd, buf, count);
- if (ret < 0)
- goto out_error;
- if ((size_t)ret != count)
- goto out_error;
- if (add_newline) {
- ret = write_nointr(fd, "\n", 1);
- if (ret != 1)
- goto out_error;
- }
- close(fd);
- return 0;
-
-out_error:
- saved_errno = errno;
- close(fd);
- errno = saved_errno;
- return -1;
-}
-
#define __ISOL_CPUS "/sys/devices/system/cpu/isolated"
static bool cg_filter_and_set_cpus(char *path, bool am_initialized)
{
lastslash = strrchr(path, '/');
if (!lastslash) { // bug... this shouldn't be possible
- pam_cgfs_debug("Invalid path: %s.\n", path);
+ pam_cgfs_debug("Invalid path: %s\n", path);
return bret;
}
+
oldv = *lastslash;
*lastslash = '\0';
+
fpath = must_make_path(path, "cpuset.cpus", NULL);
posscpus = read_file(fpath);
if (!posscpus) {
- pam_cgfs_debug("Could not read file: %s.\n", fpath);
+ pam_cgfs_debug("Could not read file: %s\n", fpath);
goto on_error;
}
/* Get maximum number of cpus found in possible cpuset. */
maxposs = cg_get_max_cpus(posscpus);
- if (maxposs < 0)
+ if (maxposs < 0 || maxposs >= INT_MAX - 1)
goto on_error;
if (!file_exists(__ISOL_CPUS)) {
/* This system doesn't expose isolated cpus. */
- pam_cgfs_debug("%s", "Path: "__ISOL_CPUS" to read isolated cpus from does not exist.\n");
+ pam_cgfs_debug("%s", "Path: "__ISOL_CPUS" to read isolated cpus from does not exist\n");
cpulist = posscpus;
+
/* No isolated cpus but we weren't already initialized by
* someone. We should simply copy the parents cpuset.cpus
* values.
*/
if (!am_initialized) {
- pam_cgfs_debug("%s", "Copying cpuset of parent cgroup.\n");
+ pam_cgfs_debug("%s", "Copying cpuset of parent cgroup\n");
goto copy_parent;
}
+
/* No isolated cpus but we were already initialized by someone.
* Nothing more to do for us.
*/
pam_cgfs_debug("%s", "Could not read file "__ISOL_CPUS"\n");
goto on_error;
}
+
if (!isdigit(isolcpus[0])) {
- pam_cgfs_debug("%s", "No isolated cpus detected.\n");
+ pam_cgfs_debug("%s", "No isolated cpus detected\n");
cpulist = posscpus;
+
/* No isolated cpus but we weren't already initialized by
* someone. We should simply copy the parents cpuset.cpus
* values.
*/
if (!am_initialized) {
- pam_cgfs_debug("%s", "Copying cpuset of parent cgroup.\n");
+ pam_cgfs_debug("%s", "Copying cpuset of parent cgroup\n");
goto copy_parent;
}
+
/* No isolated cpus but we were already initialized by someone.
* Nothing more to do for us.
*/
/* Get maximum number of cpus found in isolated cpuset. */
maxisol = cg_get_max_cpus(isolcpus);
- if (maxisol < 0)
+ if (maxisol < 0 || maxisol >= INT_MAX - 1)
goto on_error;
if (maxposs < maxisol)
possmask = cg_cpumask(posscpus, maxposs);
if (!possmask) {
- pam_cgfs_debug("%s", "Could not create cpumask for all possible cpus.\n");
+ pam_cgfs_debug("%s", "Could not create cpumask for all possible cpus\n");
goto on_error;
}
isolmask = cg_cpumask(isolcpus, maxposs);
if (!isolmask) {
- pam_cgfs_debug("%s", "Could not create cpumask for all isolated cpus.\n");
+ pam_cgfs_debug("%s", "Could not create cpumask for all isolated cpus\n");
goto on_error;
}
}
if (!flipped_bit) {
- pam_cgfs_debug("%s", "No isolated cpus present in cpuset.\n");
+ pam_cgfs_debug("%s", "No isolated cpus present in cpuset\n");
goto on_success;
}
- pam_cgfs_debug("%s", "Removed isolated cpus from cpuset.\n");
+ pam_cgfs_debug("%s", "Removed isolated cpus from cpuset\n");
cpulist = cg_cpumask_to_cpulist(possmask, maxposs);
if (!cpulist) {
- pam_cgfs_debug("%s", "Could not create cpu list.\n");
+ pam_cgfs_debug("%s", "Could not create cpu list\n");
goto on_error;
}
copy_parent:
*lastslash = oldv;
+
+ free(fpath);
+
fpath = must_make_path(path, "cpuset.cpus", NULL);
- ret = write_to_file(fpath, cpulist, strlen(cpulist), false);
+ ret = lxc_write_to_file(fpath, cpulist, strlen(cpulist), false, 0660);
if (ret < 0) {
- pam_cgfs_debug("Could not write cpu list to: %s.\n", fpath);
+ pam_cgfs_debug("Could not write cpu list to: %s\n", fpath);
goto on_error;
}
bret = true;
on_error:
- free(fpath);
+ *lastslash = oldv;
+ free(fpath);
free(isolcpus);
free(isolmask);
return bret;
}
-int read_from_file(const char *filename, void* buf, size_t count)
-{
- int fd = -1, saved_errno;
- ssize_t ret;
-
- fd = open(filename, O_RDONLY | O_CLOEXEC);
- if (fd < 0)
- return -1;
-
- if (!buf || !count) {
- char buf2[100];
- size_t count2 = 0;
- while ((ret = read(fd, buf2, 100)) > 0)
- count2 += ret;
- if (ret >= 0)
- ret = count2;
- } else {
- memset(buf, 0, count);
- ret = read(fd, buf, count);
- }
-
- if (ret < 0)
- pam_cgfs_debug("read %s: %s", filename, strerror(errno));
-
- saved_errno = errno;
- close(fd);
- errno = saved_errno;
- return ret;
-}
-
/* Copy contents of parent(@path)/@file to @path/@file */
static bool cg_copy_parent_file(char *path, char *file)
{
pam_cgfs_debug("cgfsng:copy_parent_file: bad path %s", path);
return false;
}
+
oldv = *lastslash;
*lastslash = '\0';
+
fpath = must_make_path(path, file, NULL);
- len = read_from_file(fpath, NULL, 0);
- if (len <= 0)
+ len = lxc_read_from_file(fpath, NULL, 0);
+ if (len <= 0) {
+ pam_cgfs_debug("Failed to read %s: %s", fpath, strerror(errno));
goto bad;
- value = must_alloc(len + 1);
- if (read_from_file(fpath, value, len) != len)
+ }
+
+ value = must_realloc(NULL, len + 1);
+ if (lxc_read_from_file(fpath, value, len) != len) {
+ pam_cgfs_debug("Failed to read %s: %s", fpath, strerror(errno));
goto bad;
+ }
free(fpath);
+
*lastslash = oldv;
+
fpath = must_make_path(path, file, NULL);
- ret = write_to_file(fpath, value, len, false);
+ ret = lxc_write_to_file(fpath, value, len, false, 0660);
if (ret < 0)
pam_cgfs_debug("Unable to write %s to %s", value, fpath);
+
free(fpath);
free(value);
return ret >= 0;
clonechildrenpath = must_make_path(h->mountpoint, "cgroup.clone_children", NULL);
- if (read_from_file(clonechildrenpath, &v, 1) < 0) {
- pam_cgfs_debug("Failed to read '%s'", clonechildrenpath);
+ if (lxc_read_from_file(clonechildrenpath, &v, 1) < 0) {
+ pam_cgfs_debug("Failed to read %s: %s", clonechildrenpath, strerror(errno));
free(clonechildrenpath);
return false;
}
return true;
}
- if (write_to_file(clonechildrenpath, "1", 1, false) < 0) {
+ if (lxc_write_to_file(clonechildrenpath, "1", 1, false, 0660) < 0) {
/* Set clone_children so children inherit our settings */
pam_cgfs_debug("Failed to write 1 to %s", clonechildrenpath);
free(clonechildrenpath);
return false;
}
+
free(clonechildrenpath);
return true;
}
cgpath = must_make_path(h->mountpoint, h->base_cgroup, cgroup, NULL);
if (slash)
*slash = '/';
- if (mkdir(cgpath, 0755) < 0 && errno != EEXIST) {
+
+ if (do_mkdir(cgpath, 0755) < 0 && errno != EEXIST) {
pam_cgfs_debug("Failed to create '%s'", cgpath);
free(cgpath);
return false;
}
+
clonechildrenpath = must_make_path(cgpath, "cgroup.clone_children", NULL);
if (!file_exists(clonechildrenpath)) { /* unified hierarchy doesn't have clone_children */
free(clonechildrenpath);
free(cgpath);
return true;
}
- if (read_from_file(clonechildrenpath, &v, 1) < 0) {
- pam_cgfs_debug("Failed to read '%s'", clonechildrenpath);
+
+ if (lxc_read_from_file(clonechildrenpath, &v, 1) < 0) {
+ pam_cgfs_debug("Failed to read %s: %s", clonechildrenpath, strerror(errno));
free(clonechildrenpath);
free(cgpath);
return false;
/* Make sure any isolated cpus are removed from cpuset.cpus. */
if (!cg_filter_and_set_cpus(cgpath, v == '1')) {
- pam_cgfs_debug("%s", "Failed to remove isolated cpus.\n");
+ pam_cgfs_debug("%s", "Failed to remove isolated cpus\n");
free(clonechildrenpath);
free(cgpath);
return false;
}
if (v == '1') { /* already set for us by someone else */
- pam_cgfs_debug("%s", "\"cgroup.clone_children\" was already set to \"1\".\n");
+ pam_cgfs_debug("%s", "\"cgroup.clone_children\" was already set to \"1\"\n");
free(clonechildrenpath);
free(cgpath);
return true;
/* copy parent's settings */
if (!cg_copy_parent_file(cgpath, "cpuset.mems")) {
- pam_cgfs_debug("%s", "Failed to copy \"cpuset.mems\" settings.\n");
+ pam_cgfs_debug("%s", "Failed to copy \"cpuset.mems\" settings\n");
free(cgpath);
free(clonechildrenpath);
return false;
}
free(cgpath);
- if (write_to_file(clonechildrenpath, "1", 1, false) < 0) {
+ if (lxc_write_to_file(clonechildrenpath, "1", 1, false, 0660) < 0) {
/* Set clone_children so children inherit our settings */
pam_cgfs_debug("Failed to write 1 to %s", clonechildrenpath);
free(clonechildrenpath);
*existed = false;
it = h;
+
for (controller = it->controllers; controller && *controller;
controller++) {
if (!cgv1_handle_cpuset_hierarchy(it, cgroup))
*/
if (cg_systemd_chown_existing_cgroup(it->mountpoint,
it->base_cgroup, uid, gid,
- it->systemd_user_slice)) {
+ it->systemd_user_slice))
return true;
- }
/* 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
}
path = must_make_path(it->mountpoint, it->init_cgroup, cgroup, NULL);
- pam_cgfs_debug("Constructing path: %s.\n", path);
+ pam_cgfs_debug("Constructing path: %s\n", path);
+
if (file_exists(path)) {
bool our_cg = cg_belongs_to_uid_gid(path, uid, gid);
- pam_cgfs_debug("%s existed and does %shave our uid: %d and gid: %d.\n", path, our_cg ? "" : "not ", uid, gid);
- free(path);
if (our_cg)
*existed = false;
else
*existed = true;
+
+ pam_cgfs_debug("%s existed and does %shave our uid: %d and gid: %d\n",
+ path, our_cg ? "" : "not ", uid, gid);
+ free(path);
+
return our_cg;
}
+
created = mkdir_parent(it->mountpoint, path);
if (!created) {
free(path);
continue;
}
+
if (chown(path, uid, gid) < 0)
mysyslog(LOG_WARNING,
- "Failed to chown %s to %d:%d: %s.\n", path,
- (int)uid, (int)gid, strerror(errno), NULL);
- pam_cgfs_debug("Chowned %s to %d:%d.\n", path, (int)uid, (int)gid);
+ "Failed to chown %s to %d:%d: %s\n", path,
+ (int)uid, (int)gid, strerror(errno), NULL);
+
+ pam_cgfs_debug("Chowned %s to %d:%d\n", path, (int)uid, (int)gid);
free(path);
break;
}
}
path = must_make_path(v2->mountpoint, v2->base_cgroup, cgroup, NULL);
- pam_cgfs_debug("Constructing path \"%s\".\n", path);
+ pam_cgfs_debug("Constructing path \"%s\"\n", path);
+
if (file_exists(path)) {
our_cg = cg_belongs_to_uid_gid(path, uid, gid);
- pam_cgfs_debug(
- "%s existed and does %shave our uid: %d and gid: %d.\n",
- path, our_cg ? "" : "not ", uid, gid);
+ pam_cgfs_debug("%s existed and does %shave our uid: %d and gid: %d\n",
+ path, our_cg ? "" : "not ", uid, gid);
free(path);
if (our_cg) {
*existed = false;
/* chown cgroup to user */
if (chown(path, uid, gid) < 0)
- mysyslog(LOG_WARNING, "Failed to chown %s to %d:%d: %s.\n",
- path, (int)uid, (int)gid, strerror(errno), NULL);
+ mysyslog(LOG_WARNING, "Failed to chown %s to %d:%d: %s\n",
+ path, (int)uid, (int)gid, strerror(errno), NULL);
else
- pam_cgfs_debug("Chowned %s to %d:%d.\n", path, (int)uid, (int)gid);
+ pam_cgfs_debug("Chowned %s to %d:%d\n", path, (int)uid, (int)gid);
free(path);
delegate_files:
else
path = must_make_path(v2->mountpoint, v2->base_cgroup, cgroup,
"/cgroup.procs", 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);
+ mysyslog(LOG_WARNING, "Failed to chown %s to %d:%d: %s\n",
+ path, (int)uid, (int)gid, strerror(errno), NULL);
else
- pam_cgfs_debug("Chowned %s to %d:%d.\n", path, (int)uid, (int)gid);
+ pam_cgfs_debug("Chowned %s to %d:%d\n", path, (int)uid, (int)gid);
free(path);
/* chown cgroup.subtree_control to user */
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",
+ mysyslog(LOG_WARNING, "Failed to chown %s to %d:%d: %s\n",
path, (int)uid, (int)gid, strerror(errno), NULL);
free(path);
"/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",
+ mysyslog(LOG_WARNING, "Failed to chown %s to %d:%d: %s\n",
path, (int)uid, (int)gid, strerror(errno), NULL);
free(path);
{
int idx = 0, ret;
bool existed;
- char cg[MAXPATHLEN];
+ char cg[PATH_MAX];
cg_escape();
while (idx >= 0) {
- ret = snprintf(cg, MAXPATHLEN, "/user/%s/%d", user, idx);
- if (ret < 0 || ret >= MAXPATHLEN) {
- mysyslog(LOG_ERR, "Username too long.\n", NULL);
+ ret = snprintf(cg, PATH_MAX, "/user/%s/%d", user, idx);
+ if (ret < 0 || ret >= PATH_MAX) {
+ mysyslog(LOG_ERR, "Username too long\n", NULL);
return PAM_SESSION_ERR;
}
idx++;
continue;
}
- mysyslog(LOG_ERR, "Failed to create a cgroup for user %s.\n", user, NULL);
+
+ mysyslog(LOG_ERR, "Failed to create a cgroup for user %s\n", user, NULL);
return PAM_SESSION_ERR;
}
idx++;
continue;
}
- mysyslog(LOG_ERR, "Failed to create a cgroup for user %s.\n", user, NULL);
+
+ mysyslog(LOG_ERR, "Failed to create a cgroup for user %s\n", user, NULL);
return PAM_SESSION_ERR;
}
if (!cg_enter(cg)) {
- mysyslog( LOG_ERR, "Failed to enter user cgroup %s for user %s.\n", cg, user, NULL);
+ mysyslog( LOG_ERR, "Failed to enter user cgroup %s for user %s\n", cg, user, NULL);
return PAM_SESSION_ERR;
}
+
break;
}
bool path_base_rm, path_init_rm;
path_base = must_make_path((*it)->mountpoint, (*it)->base_cgroup, "/user", user, NULL);
- pam_cgfs_debug("cgroupfs v1: Trying to prune \"%s\".\n", path_base);
+ pam_cgfs_debug("cgroupfs v1: Trying to prune \"%s\"\n", path_base);
+
ret = recursive_rmdir(path_base);
if (ret == -ENOENT || ret >= 0)
path_base_rm = true;
free(path_base);
path_init = must_make_path((*it)->mountpoint, (*it)->init_cgroup, "/user", user, NULL);
- pam_cgfs_debug("cgroupfs v1: Trying to prune \"%s\".\n", path_init);
+ pam_cgfs_debug("cgroupfs v1: Trying to prune \"%s\"\n", path_init);
+
ret = recursive_rmdir(path_init);
if (ret == -ENOENT || ret >= 0)
path_init_rm = true;
controller_removed = true;
break;
}
+
if (!controller_removed)
all_removed = false;
}
v2 = *cgv2_hierarchies;
path_base = must_make_path(v2->mountpoint, v2->base_cgroup, "/user", user, NULL);
- pam_cgfs_debug("cgroupfs v2: Trying to prune \"%s\".\n", path_base);
+ pam_cgfs_debug("cgroupfs v2: Trying to prune \"%s\"\n", path_base);
+
ret = recursive_rmdir(path_base);
if (ret == -ENOENT || ret >= 0)
path_base_rm = true;
free(path_base);
path_init = must_make_path(v2->mountpoint, v2->init_cgroup, "/user", user, NULL);
- pam_cgfs_debug("cgroupfs v2: Trying to prune \"%s\".\n", path_init);
+ pam_cgfs_debug("cgroupfs v2: Trying to prune \"%s\"\n", path_init);
+
ret = recursive_rmdir(path_init);
if (ret == -ENOENT || ret >= 0)
path_init_rm = true;
free((*it)->controllers);
}
+
free((*it)->mountpoint);
free((*it)->base_cgroup);
free((*it)->fullcgpath);
free((*it)->init_cgroup);
}
+
free(cgv1_hierarchies);
}
for (it = cgv2_hierarchies; it && *it; it++) {
if ((*it)->controllers) {
char **tmp;
+
for (tmp = (*it)->controllers; tmp && *tmp; tmp++)
free(*tmp);
free((*it)->controllers);
}
+
free((*it)->mountpoint);
free((*it)->base_cgroup);
free((*it)->fullcgpath);
free((*it)->init_cgroup);
}
+
free(cgv2_hierarchies);
}
}
if (!get_uid_gid(PAM_user, &uid, &gid)) {
- mysyslog(LOG_ERR, "Failed to get uid and gid for %s.\n", PAM_user, NULL);
+ mysyslog(LOG_ERR, "Failed to get uid and gid for %s\n", PAM_user, NULL);
return PAM_SESSION_ERR;
}
* that simply doesn't make any sense.
*/
if (string_list_length(clist) > 1 && string_in_list(clist, "all")) {
- mysyslog(LOG_ERR, "Invalid -c option, cannot specify individual controllers alongside 'all'.\n", NULL);
+ mysyslog(LOG_ERR, "Invalid -c option, cannot specify individual controllers alongside 'all'\n", NULL);
free_string_list(clist);
return PAM_SESSION_ERR;
}
}
if (!get_uid_gid(PAM_user, &uid, &gid)) {
- mysyslog(LOG_ERR, "Failed to get uid and gid for %s.\n", PAM_user, NULL);
+ mysyslog(LOG_ERR, "Failed to get uid and gid for %s\n", PAM_user, NULL);
return PAM_SESSION_ERR;
}
* that simply doesn't make any sense.
*/
if (string_list_length(clist) > 1 && string_in_list(clist, "all")) {
- mysyslog(LOG_ERR, "Invalid -c option, cannot specify individual controllers alongside 'all'.\n", NULL);
+ mysyslog(LOG_ERR, "Invalid -c option, cannot specify individual controllers alongside 'all'\n", NULL);
free_string_list(clist);
return PAM_SESSION_ERR;
}