core: rename BindMount structure → MountEntry

After all, these don#t strictly encapsulate bind mounts anymore, and we are
preparing this for adding arbitrary user-defined bind mounts in a later commit,
at which point this would become really confusing. Let's clean this up, rename
the BindMount structure to MountEntry, so that it is clear that it can contain
information about any kind of mount.
This commit is contained in:
Lennart Poettering 2016-12-14 00:48:52 +01:00
parent cfbeb4ef8d
commit 34de407a4f
1 changed files with 74 additions and 74 deletions

View File

@ -57,14 +57,14 @@ typedef enum MountMode {
READWRITE,
} MountMode;
typedef struct BindMount {
typedef struct MountEntry {
const char *path_const; /* Memory allocated on stack or static */
MountMode mode:5;
bool ignore:1; /* Ignore if path does not exist? */
bool has_prefix:1; /* Already is prefixed by the root dir? */
bool read_only:1; /* Shall this mount point be read-only? */
char *path_malloc; /* Use this instead of 'path' if we had to allocate memory */
} BindMount;
} MountEntry;
/*
* The following Protect tables are to protect paths and mark some of them
@ -75,7 +75,7 @@ typedef struct BindMount {
*/
/* ProtectKernelTunables= option and the related filesystem APIs */
static const BindMount protect_kernel_tunables_table[] = {
static const MountEntry protect_kernel_tunables_table[] = {
{ "/proc/sys", READONLY, false },
{ "/proc/sysrq-trigger", READONLY, true },
{ "/proc/latency_stats", READONLY, true },
@ -94,7 +94,7 @@ static const BindMount protect_kernel_tunables_table[] = {
};
/* ProtectKernelModules= option */
static const BindMount protect_kernel_modules_table[] = {
static const MountEntry protect_kernel_modules_table[] = {
#ifdef HAVE_SPLIT_USR
{ "/lib/modules", INACCESSIBLE, true },
#endif
@ -105,28 +105,28 @@ static const BindMount protect_kernel_modules_table[] = {
* ProtectHome=read-only table, protect $HOME and $XDG_RUNTIME_DIR and rest of
* system should be protected by ProtectSystem=
*/
static const BindMount protect_home_read_only_table[] = {
static const MountEntry protect_home_read_only_table[] = {
{ "/home", READONLY, true },
{ "/run/user", READONLY, true },
{ "/root", READONLY, true },
};
/* ProtectHome=yes table */
static const BindMount protect_home_yes_table[] = {
static const MountEntry protect_home_yes_table[] = {
{ "/home", INACCESSIBLE, true },
{ "/run/user", INACCESSIBLE, true },
{ "/root", INACCESSIBLE, true },
};
/* ProtectSystem=yes table */
static const BindMount protect_system_yes_table[] = {
static const MountEntry protect_system_yes_table[] = {
{ "/usr", READONLY, false },
{ "/boot", READONLY, true },
{ "/efi", READONLY, true },
};
/* ProtectSystem=full includes ProtectSystem=yes */
static const BindMount protect_system_full_table[] = {
static const MountEntry protect_system_full_table[] = {
{ "/usr", READONLY, false },
{ "/boot", READONLY, true },
{ "/efi", READONLY, true },
@ -141,7 +141,7 @@ static const BindMount protect_system_full_table[] = {
* (And of course /home and friends are also left writable, as ProtectHome=
* shall manage those, orthogonally).
*/
static const BindMount protect_system_strict_table[] = {
static const MountEntry protect_system_strict_table[] = {
{ "/", READONLY, false },
{ "/proc", READWRITE, false }, /* ProtectKernelTunables= */
{ "/sys", READWRITE, false }, /* ProtectKernelTunables= */
@ -151,7 +151,7 @@ static const BindMount protect_system_strict_table[] = {
{ "/root", READWRITE, true }, /* ProtectHome= */
};
static const char *bind_mount_path(const BindMount *p) {
static const char *mount_entry_path(const MountEntry *p) {
assert(p);
/* Returns the path of this bind mount. If the malloc()-allocated ->path_buffer field is set we return that,
@ -160,13 +160,13 @@ static const char *bind_mount_path(const BindMount *p) {
return p->path_malloc ?: p->path_const;
}
static bool bind_mount_read_only(const BindMount *p) {
static bool mount_entry_read_only(const MountEntry *p) {
assert(p);
return p->read_only || IN_SET(p->mode, READONLY, INACCESSIBLE);
}
static int append_access_mounts(BindMount **p, char **strv, MountMode mode) {
static int append_access_mounts(MountEntry **p, char **strv, MountMode mode) {
char **i;
assert(p);
@ -190,7 +190,7 @@ static int append_access_mounts(BindMount **p, char **strv, MountMode mode) {
if (!path_is_absolute(e))
return -EINVAL;
*((*p)++) = (BindMount) {
*((*p)++) = (MountEntry) {
.path_const = e,
.mode = mode,
.ignore = ignore,
@ -201,7 +201,7 @@ static int append_access_mounts(BindMount **p, char **strv, MountMode mode) {
return 0;
}
static int append_static_mounts(BindMount **p, const BindMount *mounts, unsigned n, bool ignore_protect) {
static int append_static_mounts(MountEntry **p, const MountEntry *mounts, unsigned n, bool ignore_protect) {
unsigned i;
assert(p);
@ -210,8 +210,8 @@ static int append_static_mounts(BindMount **p, const BindMount *mounts, unsigned
/* Adds a list of static pre-defined entries */
for (i = 0; i < n; i++)
*((*p)++) = (BindMount) {
.path_const = bind_mount_path(mounts+i),
*((*p)++) = (MountEntry) {
.path_const = mount_entry_path(mounts+i),
.mode = mounts[i].mode,
.ignore = mounts[i].ignore || ignore_protect,
};
@ -219,7 +219,7 @@ static int append_static_mounts(BindMount **p, const BindMount *mounts, unsigned
return 0;
}
static int append_protect_home(BindMount **p, ProtectHome protect_home, bool ignore_protect) {
static int append_protect_home(MountEntry **p, ProtectHome protect_home, bool ignore_protect) {
assert(p);
switch (protect_home) {
@ -238,7 +238,7 @@ static int append_protect_home(BindMount **p, ProtectHome protect_home, bool ign
}
}
static int append_protect_system(BindMount **p, ProtectSystem protect_system, bool ignore_protect) {
static int append_protect_system(MountEntry **p, ProtectSystem protect_system, bool ignore_protect) {
assert(p);
switch (protect_system) {
@ -261,11 +261,11 @@ static int append_protect_system(BindMount **p, ProtectSystem protect_system, bo
}
static int mount_path_compare(const void *a, const void *b) {
const BindMount *p = a, *q = b;
const MountEntry *p = a, *q = b;
int d;
/* If the paths are not equal, then order prefixes first */
d = path_compare(bind_mount_path(p), bind_mount_path(q));
d = path_compare(mount_entry_path(p), mount_entry_path(q));
if (d != 0)
return d;
@ -279,7 +279,7 @@ static int mount_path_compare(const void *a, const void *b) {
return 0;
}
static int prefix_where_needed(BindMount *m, unsigned n, const char *root_directory) {
static int prefix_where_needed(MountEntry *m, unsigned n, const char *root_directory) {
unsigned i;
/* Prefixes all paths in the bind mount table with the root directory if it is specified and the entry needs
@ -294,7 +294,7 @@ static int prefix_where_needed(BindMount *m, unsigned n, const char *root_direct
if (m[i].has_prefix)
continue;
s = prefix_root(root_directory, bind_mount_path(m+i));
s = prefix_root(root_directory, mount_entry_path(m+i));
if (!s)
return -ENOMEM;
@ -307,8 +307,8 @@ static int prefix_where_needed(BindMount *m, unsigned n, const char *root_direct
return 0;
}
static void drop_duplicates(BindMount *m, unsigned *n) {
BindMount *f, *t, *previous;
static void drop_duplicates(MountEntry *m, unsigned *n) {
MountEntry *f, *t, *previous;
assert(m);
assert(n);
@ -319,9 +319,9 @@ static void drop_duplicates(BindMount *m, unsigned *n) {
/* The first one wins (which is the one with the more restrictive mode), see mount_path_compare()
* above. */
if (previous && path_equal(bind_mount_path(f), bind_mount_path(previous))) {
log_debug("%s is duplicate.", bind_mount_path(f));
previous->read_only = previous->read_only || bind_mount_read_only(f); /* Propagate the read-only flag to the remaining entry */
if (previous && path_equal(mount_entry_path(f), mount_entry_path(previous))) {
log_debug("%s is duplicate.", mount_entry_path(f));
previous->read_only = previous->read_only || mount_entry_read_only(f); /* Propagate the read-only flag to the remaining entry */
f->path_malloc = mfree(f->path_malloc);
continue;
}
@ -334,8 +334,8 @@ static void drop_duplicates(BindMount *m, unsigned *n) {
*n = t - m;
}
static void drop_inaccessible(BindMount *m, unsigned *n) {
BindMount *f, *t;
static void drop_inaccessible(MountEntry *m, unsigned *n) {
MountEntry *f, *t;
const char *clear = NULL;
assert(m);
@ -348,13 +348,13 @@ static void drop_inaccessible(BindMount *m, unsigned *n) {
/* If we found a path set for INACCESSIBLE earlier, and this entry has it as prefix we should drop
* it, as inaccessible paths really should drop the entire subtree. */
if (clear && path_startswith(bind_mount_path(f), clear)) {
log_debug("%s is masked by %s.", bind_mount_path(f), clear);
if (clear && path_startswith(mount_entry_path(f), clear)) {
log_debug("%s is masked by %s.", mount_entry_path(f), clear);
f->path_malloc = mfree(f->path_malloc);
continue;
}
clear = f->mode == INACCESSIBLE ? bind_mount_path(f) : NULL;
clear = f->mode == INACCESSIBLE ? mount_entry_path(f) : NULL;
*t = *f;
t++;
@ -363,8 +363,8 @@ static void drop_inaccessible(BindMount *m, unsigned *n) {
*n = t - m;
}
static void drop_nop(BindMount *m, unsigned *n) {
BindMount *f, *t;
static void drop_nop(MountEntry *m, unsigned *n) {
MountEntry *f, *t;
assert(m);
assert(n);
@ -376,12 +376,12 @@ static void drop_nop(BindMount *m, unsigned *n) {
/* Only suppress such subtrees for READONLY and READWRITE entries */
if (IN_SET(f->mode, READONLY, READWRITE)) {
BindMount *p;
MountEntry *p;
bool found = false;
/* Now let's find the first parent of the entry we are looking at. */
for (p = t-1; p >= m; p--) {
if (path_startswith(bind_mount_path(f), bind_mount_path(p))) {
if (path_startswith(mount_entry_path(f), mount_entry_path(p))) {
found = true;
break;
}
@ -389,7 +389,7 @@ static void drop_nop(BindMount *m, unsigned *n) {
/* We found it, let's see if it's the same mode, if so, we can drop this entry */
if (found && p->mode == f->mode) {
log_debug("%s is redundant by %s", bind_mount_path(f), bind_mount_path(p));
log_debug("%s is redundant by %s", mount_entry_path(f), mount_entry_path(p));
f->path_malloc = mfree(f->path_malloc);
continue;
}
@ -402,8 +402,8 @@ static void drop_nop(BindMount *m, unsigned *n) {
*n = t - m;
}
static void drop_outside_root(const char *root_directory, BindMount *m, unsigned *n) {
BindMount *f, *t;
static void drop_outside_root(const char *root_directory, MountEntry *m, unsigned *n) {
MountEntry *f, *t;
assert(m);
assert(n);
@ -416,8 +416,8 @@ static void drop_outside_root(const char *root_directory, BindMount *m, unsigned
for (f = m, t = m; f < m + *n; f++) {
if (!path_startswith(bind_mount_path(f), root_directory)) {
log_debug("%s is outside of root directory.", bind_mount_path(f));
if (!path_startswith(mount_entry_path(f), root_directory)) {
log_debug("%s is outside of root directory.", mount_entry_path(f));
f->path_malloc = mfree(f->path_malloc);
continue;
}
@ -429,7 +429,7 @@ static void drop_outside_root(const char *root_directory, BindMount *m, unsigned
*n = t - m;
}
static int mount_dev(BindMount *m) {
static int mount_dev(MountEntry *m) {
static const char devnodes[] =
"/dev/null\0"
"/dev/zero\0"
@ -534,11 +534,11 @@ static int mount_dev(BindMount *m) {
* missing when the service is started with RootDirectory. This is
* consistent with mount units creating the mount points when missing.
*/
(void) mkdir_p_label(bind_mount_path(m), 0755);
(void) mkdir_p_label(mount_entry_path(m), 0755);
/* Unmount everything in old /dev */
umount_recursive(bind_mount_path(m), 0);
if (mount(dev, bind_mount_path(m), NULL, MS_MOVE, NULL) < 0) {
umount_recursive(mount_entry_path(m), 0);
if (mount(dev, mount_entry_path(m), NULL, MS_MOVE, NULL) < 0) {
r = -errno;
goto fail;
}
@ -569,7 +569,7 @@ fail:
}
static int apply_mount(
BindMount *m,
MountEntry *m,
const char *tmp_dir,
const char *var_tmp_dir) {
@ -578,7 +578,7 @@ static int apply_mount(
assert(m);
log_debug("Applying namespace mount on %s", bind_mount_path(m));
log_debug("Applying namespace mount on %s", mount_entry_path(m));
switch (m->mode) {
@ -588,10 +588,10 @@ static int apply_mount(
/* First, get rid of everything that is below if there
* is anything... Then, overmount it with an
* inaccessible path. */
(void) umount_recursive(bind_mount_path(m), 0);
(void) umount_recursive(mount_entry_path(m), 0);
if (lstat(bind_mount_path(m), &target) < 0)
return log_debug_errno(errno, "Failed to lstat() %s to determine what to mount over it: %m", bind_mount_path(m));
if (lstat(mount_entry_path(m), &target) < 0)
return log_debug_errno(errno, "Failed to lstat() %s to determine what to mount over it: %m", mount_entry_path(m));
what = mode_to_inaccessible_node(target.st_mode);
if (!what) {
@ -604,13 +604,13 @@ static int apply_mount(
case READONLY:
case READWRITE:
r = path_is_mount_point(bind_mount_path(m), NULL, 0);
r = path_is_mount_point(mount_entry_path(m), NULL, 0);
if (r < 0)
return log_debug_errno(r, "Failed to determine whether %s is already a mount point: %m", bind_mount_path(m));
return log_debug_errno(r, "Failed to determine whether %s is already a mount point: %m", mount_entry_path(m));
if (r > 0) /* Nothing to do here, it is already a mount. We just later toggle the MS_RDONLY bit for the mount point if needed. */
return 0;
/* This isn't a mount point yet, let's make it one. */
what = bind_mount_path(m);
what = mount_entry_path(m);
break;
case PRIVATE_TMP:
@ -630,22 +630,22 @@ static int apply_mount(
assert(what);
if (mount(what, bind_mount_path(m), NULL, MS_BIND|MS_REC, NULL) < 0)
return log_debug_errno(errno, "Failed to mount %s to %s: %m", what, bind_mount_path(m));
if (mount(what, mount_entry_path(m), NULL, MS_BIND|MS_REC, NULL) < 0)
return log_debug_errno(errno, "Failed to mount %s to %s: %m", what, mount_entry_path(m));
log_debug("Successfully mounted %s to %s", what, bind_mount_path(m));
log_debug("Successfully mounted %s to %s", what, mount_entry_path(m));
return 0;
}
static int make_read_only(BindMount *m, char **blacklist) {
static int make_read_only(MountEntry *m, char **blacklist) {
int r = 0;
assert(m);
if (bind_mount_read_only(m))
r = bind_remount_recursive(bind_mount_path(m), true, blacklist);
if (mount_entry_read_only(m))
r = bind_remount_recursive(mount_entry_path(m), true, blacklist);
else if (m->mode == PRIVATE_DEV) { /* Can be readonly but the submounts can't*/
if (mount(NULL, bind_mount_path(m), NULL, MS_REMOUNT|DEV_MOUNT_OPTIONS|MS_RDONLY, NULL) < 0)
if (mount(NULL, mount_entry_path(m), NULL, MS_REMOUNT|DEV_MOUNT_OPTIONS|MS_RDONLY, NULL) < 0)
r = -errno;
} else
return 0;
@ -658,8 +658,8 @@ static int make_read_only(BindMount *m, char **blacklist) {
}
/* Chase symlinks and remove failed paths from mounts */
static int chase_all_symlinks(const char *root_directory, BindMount *m, unsigned *n) {
BindMount *f, *t;
static int chase_all_symlinks(const char *root_directory, MountEntry *m, unsigned *n) {
MountEntry *f, *t;
int r = 0;
assert(m);
@ -673,20 +673,20 @@ static int chase_all_symlinks(const char *root_directory, BindMount *m, unsigned
_cleanup_free_ char *chased = NULL;
int k;
k = chase_symlinks(bind_mount_path(f), root_directory, 0, &chased);
k = chase_symlinks(mount_entry_path(f), root_directory, 0, &chased);
if (k < 0) {
/* Get only real errors */
if (r >= 0 && (k != -ENOENT || !f->ignore))
r = k;
/* Doesn't exist or failed? Then remove it and continue! */
log_debug_errno(k, "Failed to chase symlinks for %s: %m", bind_mount_path(f));
log_debug_errno(k, "Failed to chase symlinks for %s: %m", mount_entry_path(f));
f->path_malloc = mfree(f->path_malloc);
continue;
}
if (!path_equal(bind_mount_path(f), chased)) {
log_debug("Chased %s → %s", bind_mount_path(f), chased);
if (!path_equal(mount_entry_path(f), chased)) {
log_debug("Chased %s → %s", mount_entry_path(f), chased);
free(f->path_malloc);
f->path_malloc = chased;
@ -749,7 +749,7 @@ int setup_namespace(
ProtectSystem protect_system,
unsigned long mount_flags) {
BindMount *m, *mounts = NULL;
MountEntry *m, *mounts = NULL;
bool make_slave = false;
unsigned n_mounts;
int r = 0;
@ -770,7 +770,7 @@ int setup_namespace(
make_slave = true;
if (n_mounts > 0) {
m = mounts = (BindMount *) alloca0(n_mounts * sizeof(BindMount));
m = mounts = (MountEntry *) alloca0(n_mounts * sizeof(MountEntry));
r = append_access_mounts(&m, read_write_paths, READWRITE);
if (r < 0)
goto finish;
@ -784,21 +784,21 @@ int setup_namespace(
goto finish;
if (tmp_dir) {
*(m++) = (BindMount) {
*(m++) = (MountEntry) {
.path_const = "/tmp",
.mode = PRIVATE_TMP,
};
}
if (var_tmp_dir) {
*(m++) = (BindMount) {
*(m++) = (MountEntry) {
.path_const = "/var/tmp",
.mode = PRIVATE_VAR_TMP,
};
}
if (ns_info->private_dev) {
*(m++) = (BindMount) {
*(m++) = (MountEntry) {
.path_const = "/dev",
.mode = PRIVATE_DEV,
};
@ -817,7 +817,7 @@ int setup_namespace(
}
if (ns_info->protect_control_groups) {
*(m++) = (BindMount) {
*(m++) = (MountEntry) {
.path_const = "/sys/fs/cgroup",
.mode = READONLY,
};
@ -845,7 +845,7 @@ int setup_namespace(
if (r < 0)
goto finish;
qsort(mounts, n_mounts, sizeof(BindMount), mount_path_compare);
qsort(mounts, n_mounts, sizeof(MountEntry), mount_path_compare);
drop_duplicates(mounts, &n_mounts);
drop_outside_root(root_directory, mounts, &n_mounts);
@ -894,7 +894,7 @@ int setup_namespace(
/* Create a blacklist we can pass to bind_mount_recursive() */
blacklist = newa(char*, n_mounts+1);
for (j = 0; j < n_mounts; j++)
blacklist[j] = (char*) bind_mount_path(mounts+j);
blacklist[j] = (char*) mount_entry_path(mounts+j);
blacklist[j] = NULL;
/* Second round, flip the ro bits if necessary. */