#include <libgen.h>
#include <assert.h>
#include <unistd.h>
+#include <ftw.h>
#include "mount-setup.h"
#include "log.h"
#include "util.h"
#include "label.h"
+#ifndef TTY_GID
+#define TTY_GID 5
+#endif
+
typedef struct MountPoint {
const char *what;
const char *where;
{ "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, true },
{ "sysfs", "/sys", "sysfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, true },
{ "devtmpfs", "/dev", "devtmpfs", "mode=755", MS_NOSUID, true },
- { "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NOEXEC|MS_NODEV, true },
- { "devpts", "/dev/pts", "devpts", NULL, MS_NOSUID|MS_NOEXEC, false },
- { "tmpfs", "/sys/fs/cgroup", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV, true },
- { "cgroup", "/sys/fs/cgroup/systemd", "cgroup", "none,name=systemd", MS_NOSUID|MS_NOEXEC|MS_NODEV, true },
+ { "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV, true },
+ { "devpts", "/dev/pts", "devpts", "mode=620,gid=" STRINGIFY(TTY_GID), MS_NOSUID|MS_NOEXEC, false },
+ { "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV, true },
+ { "tmpfs", "/sys/fs/cgroup", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV, false },
+ { "cgroup", "/sys/fs/cgroup/systemd", "cgroup", "none,name=systemd", MS_NOSUID|MS_NOEXEC|MS_NODEV, false },
};
/* These are API file systems that might be mounted by other software,
- * we just list them here so that we know that we should igore them */
+ * we just list them here so that we know that we should ignore them */
static const char * const ignore_paths[] = {
+ "/sys/fs/selinux",
"/selinux",
- "/proc/bus/usb",
- "/var/lib/nfs/rpc_pipefs",
- "/proc/fs/nfsd"
+ "/proc/bus/usb"
};
bool mount_point_is_api(const char *path) {
if (path_equal(path, mount_table[i].where))
return true;
+ return path_startswith(path, "/sys/fs/cgroup/");
+}
+
+bool mount_point_ignore(const char *path) {
+ unsigned i;
+
for (i = 0; i < ELEMENTSOF(ignore_paths); i++)
if (path_equal(path, ignore_paths[i]))
return true;
- return path_startswith(path, "/sys/fs/cgroup/");
+ return false;
}
static int mount_one(const MountPoint *p) {
assert(p);
+ /* Relabel first, just in case */
+ label_fix(p->where, true);
+
if ((r = path_is_mount_point(p->where)) < 0)
return r;
return p->fatal ? -errno : 0;
}
- label_fix(p->where);
+ /* Relabel again, since we now mounted something fresh here */
+ label_fix(p->where, false);
return 0;
}
static int mount_cgroup_controllers(void) {
int r;
FILE *f;
- char buf [256];
+ char buf[LINE_MAX];
/* Mount all available cgroup controllers that are built into the kernel. */
- if (!(f = fopen("/proc/cgroups", "re")))
- return -ENOENT;
+ if (!(f = fopen("/proc/cgroups", "re"))) {
+ log_error("Failed to enumerate cgroup controllers: %m");
+ return 0;
+ }
/* Ignore the header line */
(void) fgets(buf, sizeof(buf), f);
for (;;) {
MountPoint p;
char *controller, *where;
+ int enabled = false;
- if (fscanf(f, "%ms %*i %*i %*i", &controller) != 1) {
+ if (fscanf(f, "%ms %*i %*i %i", &controller, &enabled) != 2) {
if (feof(f))
break;
goto finish;
}
+ if (!enabled) {
+ free(controller);
+ continue;
+ }
+
if (asprintf(&where, "/sys/fs/cgroup/%s", controller) < 0) {
free(controller);
r = -ENOMEM;
return r;
}
+static int nftw_cb(
+ const char *fpath,
+ const struct stat *sb,
+ int tflag,
+ struct FTW *ftwbuf) {
+
+ /* No need to label /dev twice in a row... */
+ if (ftwbuf->level == 0)
+ return 0;
+
+ label_fix(fpath, true);
+ return 0;
+};
+
int mount_setup(void) {
- const char *symlinks =
+ const char symlinks[] =
"/proc/kcore\0" "/dev/core\0"
"/proc/self/fd\0" "/dev/fd\0"
"/proc/self/fd/0\0" "/dev/stdin\0"
"/proc/self/fd/1\0" "/dev/stdout\0"
- "/proc/self/fd/2\0" "/dev/stderr\0"
- "\0";
+ "/proc/self/fd/2\0" "/dev/stderr\0";
int r;
unsigned i;
if ((r = mount_one(mount_table+i)) < 0)
return r;
+ /* Nodes in devtmpfs and /run need to be manually updated for
+ * the appropriate labels, after mounting. The other virtual
+ * API file systems like /sys and /proc do not need that, they
+ * use the same label for all their files. */
+ if (unlink("/dev/.systemd-relabel-run-dev") >= 0) {
+ nftw("/dev", nftw_cb, 64, FTW_MOUNT|FTW_PHYS);
+ nftw("/run", nftw_cb, 64, FTW_MOUNT|FTW_PHYS);
+ }
+
/* Create a few default symlinks, which are normally created
- * bei udevd, but some scripts might need them before we start
+ * by udevd, but some scripts might need them before we start
* udevd. */
-
NULSTR_FOREACH_PAIR(j, k, symlinks)
symlink_and_label(j, k);
+ /* Create a few directories we always want around */
+ mkdir("/run/systemd", 0755);
+ mkdir("/run/systemd/system", 0755);
+
return mount_cgroup_controllers();
}