* 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)
{
{
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])
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)
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)) {
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;
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;
}
/* 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;
}
free(hierarchies);
free(fd_hierarchies);
+
+ if (cgroup_mount_ns_fd >= 0)
+ close(cgroup_mount_ns_fd);
}
*/
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;
*/
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
free(path);
if (our_cg) {
*existed = false;
- goto chown_cgroup_procs_file;
+ goto delegate_files;
} else {
*existed = true;
return false;
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,
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;
}