]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
mount-util: add helpers for mount() without following symlinks
authorLennart Poettering <lennart@poettering.net>
Tue, 22 Sep 2020 13:16:15 +0000 (15:16 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 23 Sep 2020 16:57:36 +0000 (18:57 +0200)
src/shared/mount-util.c
src/shared/mount-util.h

index 53fb46e7bca1ccb1912bd6a0343750f65db2fbaa..76308a8b0653af9b6f669b39db9ac14cee29ef70 100644 (file)
 #include "parse-util.h"
 #include "path-util.h"
 #include "set.h"
+#include "stat-util.h"
 #include "stdio-util.h"
 #include "string-util.h"
 #include "strv.h"
 
+int mount_fd(const char *source,
+             int target_fd,
+             const char *filesystemtype,
+             unsigned long mountflags,
+             const void *data) {
+
+        char path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+
+        xsprintf(path, "/proc/self/fd/%i", target_fd);
+        if (mount(source, path, filesystemtype, mountflags, data) < 0) {
+                if (errno != ENOENT)
+                        return -errno;
+
+                /* ENOENT can mean two things: either that the source is missing, or that /proc/ isn't
+                 * mounted. Check for the latter to generate better error messages. */
+                if (proc_mounted() == 0)
+                        return -ENOSYS;
+
+                return -ENOENT;
+        }
+
+        return 0;
+}
+
+int mount_nofollow(
+                const char *source,
+                const char *target,
+                const char *filesystemtype,
+                unsigned long mountflags,
+                const void *data) {
+
+        _cleanup_close_ int fd = -1;
+
+        /* In almost all cases we want to manipulate the mount table without following symlinks, hence
+         * mount_nofollow() is usually the way to go. The only exceptions are environments where /proc/ is
+         * not available yet, since we need /proc/self/fd/ for this logic to work. i.e. during the early
+         * initialization of namespacing/container stuff where /proc is not yet mounted (and maybe even the
+         * fs to mount) we can only use traditional mount() directly.
+         *
+         * Note that this disables following only for the final component of the target, i.e symlinks within
+         * the path of the target are honoured, as are symlinks in the source path everywhere. */
+
+        fd = open(target, O_PATH|O_CLOEXEC|O_NOFOLLOW);
+        if (fd < 0)
+                return -errno;
+
+        return mount_fd(source, fd, filesystemtype, mountflags, data);
+}
+
 int umount_recursive(const char *prefix, int flags) {
         int n = 0, r;
         bool again;
index 8fb597e7c039de33ba61a04b5ee5692d61c91153..3c74ad44876c681f76dd63457c7ab13ddcb43a55 100644 (file)
@@ -32,6 +32,9 @@
 #define TMPFS_LIMITS_ROOTFS          TMPFS_LIMITS_VAR
 #define TMPFS_LIMITS_VOLATILE_STATE  TMPFS_LIMITS_VAR
 
+int mount_fd(const char *source, int target_fd, const char *filesystemtype, unsigned long mountflags, const void *data);
+int mount_nofollow(const char *source, const char *target, const char *filesystemtype, unsigned long mountflags, const void *data);
+
 int repeat_unmount(const char *path, int flags);
 int umount_recursive(const char *target, int flags);
 int bind_remount_recursive(const char *prefix, unsigned long new_flags, unsigned long flags_mask, char **deny_list);