mirror of
https://github.com/systemd/systemd.git
synced 2025-01-20 18:04:03 +03:00
core: open /proc/self/mountinfo early to allow mounts over /proc (#5985)
Enable masking the /proc folder using the 'InaccessiblePaths' unit option. This also slightly simplify mounts setup as the bind_remount_recursive function will only open /proc/self/mountinfo once. This is based on the suggestion at: https://lists.freedesktop.org/archives/systemd-devel/2017-April/038634.html
This commit is contained in:
parent
215a2db419
commit
ac9de0b379
@ -317,11 +317,16 @@ static int get_mount_flags(const char *path, unsigned long *flags) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bind_remount_recursive(const char *prefix, bool ro, char **blacklist) {
|
||||
/* Use this function only if do you have direct access to /proc/self/mountinfo
|
||||
* and need the caller to open it for you. This is the case when /proc is
|
||||
* masked or not mounted. Otherwise, use bind_remount_recursive. */
|
||||
int bind_remount_recursive_with_mountinfo(const char *prefix, bool ro, char **blacklist, FILE *proc_self_mountinfo) {
|
||||
_cleanup_set_free_free_ Set *done = NULL;
|
||||
_cleanup_free_ char *cleaned = NULL;
|
||||
int r;
|
||||
|
||||
assert(proc_self_mountinfo);
|
||||
|
||||
/* Recursively remount a directory (and all its submounts) read-only or read-write. If the directory is already
|
||||
* mounted, we reuse the mount and simply mark it MS_BIND|MS_RDONLY (or remove the MS_RDONLY for read-write
|
||||
* operation). If it isn't we first make it one. Afterwards we apply MS_BIND|MS_RDONLY (or remove MS_RDONLY) to
|
||||
@ -344,7 +349,6 @@ int bind_remount_recursive(const char *prefix, bool ro, char **blacklist) {
|
||||
return -ENOMEM;
|
||||
|
||||
for (;;) {
|
||||
_cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
|
||||
_cleanup_set_free_free_ Set *todo = NULL;
|
||||
bool top_autofs = false;
|
||||
char *x;
|
||||
@ -354,9 +358,7 @@ int bind_remount_recursive(const char *prefix, bool ro, char **blacklist) {
|
||||
if (!todo)
|
||||
return -ENOMEM;
|
||||
|
||||
proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
|
||||
if (!proc_self_mountinfo)
|
||||
return -errno;
|
||||
rewind(proc_self_mountinfo);
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *path = NULL, *p = NULL, *type = NULL;
|
||||
@ -495,6 +497,16 @@ int bind_remount_recursive(const char *prefix, bool ro, char **blacklist) {
|
||||
}
|
||||
}
|
||||
|
||||
int bind_remount_recursive(const char *prefix, bool ro, char **blacklist) {
|
||||
_cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
|
||||
|
||||
proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
|
||||
if (!proc_self_mountinfo)
|
||||
return -errno;
|
||||
|
||||
return bind_remount_recursive_with_mountinfo(prefix, ro, blacklist, proc_self_mountinfo);
|
||||
}
|
||||
|
||||
int mount_move_root(const char *path) {
|
||||
assert(path);
|
||||
|
||||
|
@ -36,6 +36,7 @@ int repeat_unmount(const char *path, int flags);
|
||||
|
||||
int umount_recursive(const char *target, int flags);
|
||||
int bind_remount_recursive(const char *prefix, bool ro, char **blacklist);
|
||||
int bind_remount_recursive_with_mountinfo(const char *prefix, bool ro, char **blacklist, FILE *proc_self_mountinfo);
|
||||
|
||||
int mount_move_root(const char *path);
|
||||
|
||||
|
@ -793,13 +793,14 @@ static int apply_mount(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int make_read_only(MountEntry *m, char **blacklist) {
|
||||
static int make_read_only(MountEntry *m, char **blacklist, FILE *proc_self_mountinfo) {
|
||||
int r = 0;
|
||||
|
||||
assert(m);
|
||||
assert(proc_self_mountinfo);
|
||||
|
||||
if (mount_entry_read_only(m))
|
||||
r = bind_remount_recursive(mount_entry_path(m), true, blacklist);
|
||||
r = bind_remount_recursive_with_mountinfo(mount_entry_path(m), true, blacklist, proc_self_mountinfo);
|
||||
else if (m->mode == PRIVATE_DEV) { /* Superblock can be readonly but the submounts can't */
|
||||
if (mount(NULL, mount_entry_path(m), NULL, MS_REMOUNT|DEV_MOUNT_OPTIONS|MS_RDONLY, NULL) < 0)
|
||||
r = -errno;
|
||||
@ -1082,9 +1083,18 @@ int setup_namespace(
|
||||
}
|
||||
|
||||
if (n_mounts > 0) {
|
||||
_cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
|
||||
char **blacklist;
|
||||
unsigned j;
|
||||
|
||||
/* Open /proc/self/mountinfo now as it may become unavailable if we mount anything on top of /proc.
|
||||
* For example, this is the case with the option: 'InaccessiblePaths=/proc' */
|
||||
proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
|
||||
if (!proc_self_mountinfo) {
|
||||
r = -errno;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
/* First round, add in all special mounts we need */
|
||||
for (m = mounts; m < mounts + n_mounts; ++m) {
|
||||
r = apply_mount(root_directory, m, tmp_dir, var_tmp_dir);
|
||||
@ -1100,7 +1110,7 @@ int setup_namespace(
|
||||
|
||||
/* Second round, flip the ro bits if necessary. */
|
||||
for (m = mounts; m < mounts + n_mounts; ++m) {
|
||||
r = make_read_only(m, blacklist);
|
||||
r = make_read_only(m, blacklist, proc_self_mountinfo);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user