return mount_nofollow_verbose(LOG_DEBUG, "/sys", mount_entry_path(m), NULL, MS_BIND|MS_REC, NULL);
}
-static int mount_private_sysfs(const MountEntry *m) {
- const char *entry_path = mount_entry_path(ASSERT_PTR(m));
+static int mount_private_apivfs(
+ const char *fstype,
+ const char *entry_path,
+ const char *bind_source,
+ const char *opts) {
+
int r, n;
- (void) mkdir_p_label(entry_path, 0755);
+ assert(fstype);
+ assert(entry_path);
+ assert(bind_source);
- n = umount_recursive(entry_path, 0);
+ (void) mkdir_p_label(entry_path, 0755);
+ n = umount_recursive(entry_path, /* flags = */ 0);
- r = mount_nofollow_verbose(LOG_DEBUG, "sysfs", entry_path, "sysfs", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL);
+ r = mount_nofollow_verbose(LOG_DEBUG, fstype, entry_path, fstype, MS_NOSUID|MS_NOEXEC|MS_NODEV, opts);
+ if (r == -EINVAL && opts)
+ /* If this failed with EINVAL then this likely means the textual hidepid= stuff for procfs is
+ * not supported by the kernel, and thus the per-instance hidepid= neither, which means we
+ * really don't want to use it, since it would affect our host's /proc mount. Hence let's
+ * gracefully fallback to a classic, unrestricted version. */
+ r = mount_nofollow_verbose(LOG_DEBUG, fstype, entry_path, fstype, MS_NOSUID|MS_NOEXEC|MS_NODEV, /* opts = */ NULL);
if (ERRNO_IS_NEG_PRIVILEGE(r)) {
- /* When we do not have enough privileges to mount sysfs, fall back to use existing /sys. */
+ /* When we do not have enough privileges to mount a new instance, fall back to use an
+ * existing mount. */
if (n > 0)
- /* /sys or some of sub-mounts are umounted in the above. Refuse incomplete tree.
+ /* The mount or some of sub-mounts are umounted in the above. Refuse incomplete tree.
* Propagate the original error code returned by mount() in the above. */
return r;
- return mount_bind_sysfs(m);
+ r = path_is_mount_point(entry_path, /* root = */ NULL, /* flags = */ 0);
+ if (r < 0)
+ return log_debug_errno(r, "Unable to determine whether '%s' is already mounted: %m", entry_path);
+ if (r > 0)
+ return 0; /* Use the current mount as is. */
+
+ /* We lack permissions to mount a new instance, and it is not already mounted. But we can
+ * access the host's, so as a final fallback bind-mount it to the destination, as most likely
+ * we are inside a user manager in an unprivileged user namespace. */
+ return mount_nofollow_verbose(LOG_DEBUG, bind_source, entry_path, /* fstype = */ NULL, MS_BIND|MS_REC, /* opts = */ NULL);
} else if (r < 0)
return r;
- /* We mounted a new instance now. Let's bind mount the children over now. */
- (void) bind_mount_submounts("/sys", entry_path);
+ /* We mounted a new instance now. Let's bind mount the children over now. This matters for nspawn
+ * where a bunch of files are overmounted, in particular the boot id. */
+ (void) bind_mount_submounts(bind_source, entry_path);
return 0;
}
+static int mount_private_sysfs(const MountEntry *m) {
+ assert(m);
+ return mount_private_apivfs("sysfs", mount_entry_path(m), "/sys", /* opts = */ NULL);
+}
+
static int mount_procfs(const MountEntry *m, const NamespaceParameters *p) {
_cleanup_free_ char *opts = NULL;
- const char *entry_path;
- int r, n;
assert(m);
assert(p);
return -ENOMEM;
}
- entry_path = mount_entry_path(m);
- (void) mkdir_p_label(entry_path, 0755);
-
/* Mount a new instance, so that we get the one that matches our user namespace, if we are running in
* one. i.e we don't reuse existing mounts here under any condition, we want a new instance owned by
* our user namespace and with our hidepid= settings applied. Hence, let's get rid of everything
* mounted on /proc/ first. */
-
- n = umount_recursive(entry_path, 0);
-
- r = mount_nofollow_verbose(LOG_DEBUG, "proc", entry_path, "proc", MS_NOSUID|MS_NOEXEC|MS_NODEV, opts);
- if (r == -EINVAL && opts)
- /* If this failed with EINVAL then this likely means the textual hidepid= stuff is
- * not supported by the kernel, and thus the per-instance hidepid= neither, which
- * means we really don't want to use it, since it would affect our host's /proc
- * mount. Hence let's gracefully fallback to a classic, unrestricted version. */
- r = mount_nofollow_verbose(LOG_DEBUG, "proc", entry_path, "proc", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL);
- if (ERRNO_IS_NEG_PRIVILEGE(r)) {
- /* When we do not have enough privileges to mount /proc, fall back to use existing /proc. */
-
- if (n > 0)
- /* /proc or some of sub-mounts are umounted in the above. Refuse incomplete tree.
- * Propagate the original error code returned by mount() in the above. */
- return r;
-
- r = path_is_mount_point(entry_path, NULL, 0);
- if (r < 0)
- return log_debug_errno(r, "Unable to determine whether /proc is already mounted: %m");
- if (r > 0)
- return 0;
-
- /* We lack permissions to mount a new instance of /proc, and it is not already mounted. But
- * we can access the host's, so as a final fallback bind-mount it to the destination, as most
- * likely we are inside a user manager in an unprivileged user namespace. */
- return mount_nofollow_verbose(LOG_DEBUG, "/proc", entry_path, NULL, MS_BIND|MS_REC, NULL);
-
- } else if (r < 0)
- return r;
-
- /* We mounted a new instance now. Let's bind mount the children over now. This matters for nspawn
- * where a bunch of files are overmounted, in particular the boot id */
- (void) bind_mount_submounts("/proc", entry_path);
- return 0;
+ return mount_private_apivfs("proc", mount_entry_path(m), "/proc", opts);
}
static int mount_tmpfs(const MountEntry *m) {