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
return -ENOMEM;
for (;;) {
- _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
_cleanup_set_free_free_ Set *todo = NULL;
bool top_autofs = false;
char *x;
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;
}
}
+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);
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);
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;
}
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);
/* 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;
}