diff --git a/src/core/namespace.c b/src/core/namespace.c index e9702ae448..1b4bcd5ba4 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -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. */