]> git.ipfire.org Git - pakfire.git/commitdiff
execute: Mount all file systems only in namespace
authorMichael Tremer <michael.tremer@ipfire.org>
Sun, 17 Jul 2022 18:16:04 +0000 (18:16 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sun, 17 Jul 2022 18:16:04 +0000 (18:16 +0000)
If Pakfire is running as an unprivileged user, we cannot call mount() in
the original namespace. However, it is difficult to spawn a new process
in a new namespace first and then perform loads of actions in there.
Embedded Pakfire would become more difficult.

At the cost of losing the option to create an environment in a
dynamically created ramdisk, we can only mount everything when we enter
the container.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/execute.c
src/libpakfire/include/pakfire/mount.h
src/libpakfire/mount.c
src/libpakfire/pakfire.c

index 1780b3436828edaaca8148d5a2e24501f2bd75c2..27a07aae0d51dc5f0a7d0fe77b20e5a12fdbc746 100644 (file)
@@ -556,7 +556,7 @@ static int pakfire_execute_fork(void* data) {
        // Change root (unless root is /)
        if (strcmp(root, "/") != 0) {
                // Mount everything
-               r = pakfire_mount_all(pakfire, MOUNT_IN_NEW_NS);
+               r = pakfire_mount_all(pakfire);
                if (r)
                        return r;
 
@@ -846,7 +846,7 @@ ERROR:
                close(env.stderr[0]);
 
        // Umount everything
-       pakfire_umount_all(pakfire, PAKFIRE_MOUNT_OPT_NAMESPACED);
+       pakfire_umount_all(pakfire);
 
        // Free environment
        for (unsigned int i = 0; env.envp[i]; i++)
index fba1ae735e1c17e7ac2a2a839a1d90f7dce7ec72..20330e08c477c4ba48fe03b8eb3a163038880dec 100644 (file)
 
 #include <pakfire/pakfire.h>
 
-#define PAKFIRE_MOUNT_OPT_NAMESPACED "x-pakfire.ns" // "_pakfire_ns"
-
-enum pakfire_mount_flags {
-       MOUNT_IN_NEW_NS = (1 << 0),
-};
-
 int pakfire_mount_list(struct pakfire* pakfire);
 
 int pakfire_mount(struct pakfire* pakfire, const char* source, const char* target,
        const char* filesystemtype, unsigned long mountflags, const void* data);
 
-int pakfire_mount_all(struct pakfire* pakfire, const enum pakfire_mount_flags mount_flags);
-int pakfire_umount_all(struct pakfire* pakfire, const char* option);
+int pakfire_mount_all(struct pakfire* pakfire);
+int pakfire_umount_all(struct pakfire* pakfire);
 
 #endif /* PAKFIRE_PRIVATE */
index 67313d4466a3dd277310caf939f20715344730e7..f7b1b966ad4ee16c584541a831c7b4dae02b80f0 100644 (file)
@@ -23,6 +23,7 @@
 #include <stddef.h>
 #include <sys/mount.h>
 #include <sys/stat.h>
+#include <sys/sysmacros.h>
 #include <sys/types.h>
 
 // libmount
@@ -39,60 +40,72 @@ static const struct pakfire_mountpoint {
        const char* fstype;
        int flags;
        const char* options;
-       enum pakfire_mount_flags mount_flags;
 } mountpoints[] = {
-       // The root filesystem is a tmpfs
-       { "pakfire_root",  "",             "tmpfs", 0, NULL, 0 },
-
-       { "pakfire_proc",  "proc",         "proc",  MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL,
-               MOUNT_IN_NEW_NS },
+       { "pakfire_proc",  "proc",         "proc",  MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL, },
 
        // Bind mount /proc/sys as read-only with the following exceptions:
        //  * /proc/sys/net
-       { "/proc/sys",     "proc/sys",     "bind",  MS_BIND, NULL,
-               MOUNT_IN_NEW_NS },
-       { "/proc/sys/net", "proc/sys/net", "bind",  MS_BIND, NULL,
-               MOUNT_IN_NEW_NS },
-       { "/proc/sys",     "proc/sys",     "bind",  MS_BIND|MS_RDONLY|MS_REMOUNT, NULL,
-               MOUNT_IN_NEW_NS },
+       { "/proc/sys",     "proc/sys",     "bind",  MS_BIND, NULL, },
+       { "/proc/sys/net", "proc/sys/net", "bind",  MS_BIND, NULL, },
+       { "/proc/sys",     "proc/sys",     "bind",  MS_BIND|MS_RDONLY|MS_REMOUNT, NULL, },
 
        // Bind mount /sys as read-only
-       { "/sys",          "sys",          "bind",  MS_BIND, NULL, },
-       { "/sys",          "sys",          "bind",  MS_BIND|MS_RDONLY|MS_REMOUNT, NULL, },
+       { "/sys",          "sys",          "bind",  MS_BIND, NULL, },
+       { "/sys",          "sys",          "bind",  MS_BIND|MS_RDONLY|MS_REMOUNT, NULL, },
 
        // Create a new /dev
        { "pakfire_dev",   "dev",          "tmpfs", MS_NOSUID|MS_NOEXEC,
-               "mode=755,size=4m,nr_inodes=64k", },
-       { "/dev/pts",      "dev/pts",      "bind",  MS_BIND, NULL, },
+               "mode=755,size=4m,nr_inodes=64k", },
+       { "/dev/pts",      "dev/pts",      "bind",  MS_BIND, NULL, },
 
        // Create a new /run
        { "pakfire_tmpfs", "run",          "tmpfs", MS_NOSUID|MS_NOEXEC|MS_NODEV,
-               "mode=755,size=4m,nr_inodes=1k", },
+               "mode=755,size=4m,nr_inodes=1k", },
 
        // Create a new /tmp
-       { "pakfire_tmpfs", "tmp",          "tmpfs", MS_NOSUID|MS_NODEV,
-               "mode=755", 0 },
+       { "pakfire_tmpfs", "tmp",          "tmpfs", MS_NOSUID|MS_NODEV, "mode=755", },
 
        // The end
        { NULL },
 };
 
-int pakfire_disable_mount_propagation(struct pakfire* pakfire, const char* path) {
-       DEBUG(pakfire, "Disabling mount propagation on %s\n", path);
-
-       int r = mount(NULL, path, NULL, MS_REC|MS_PRIVATE, NULL);
-       if (r)
-               ERROR(pakfire, "Failed to set mount propagation on %s to private: %m", path);
+static const struct pakfire_devnode {
+       const char* path;
+       int major;
+       int minor;
+       mode_t mode;
+} devnodes[] = {
+       { "/dev/null",      1,  3, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH, },
+       { "/dev/zero",      1,  5, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH, },
+       { "/dev/full",      1,  7, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH, },
+       { "/dev/random",    1,  8, S_IFCHR|S_IRUSR|S_IRGRP|S_IROTH, },
+       { "/dev/urandom",   1,  9, S_IFCHR|S_IRUSR|S_IRGRP|S_IROTH, },
+       { "/dev/kmsg",      1, 11, S_IFCHR|S_IRUSR|S_IRGRP|S_IROTH, },
+       { "/dev/tty",       5,  0, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH, },
+       { "/dev/console",   5,  1, S_IFCHR|S_IRUSR|S_IWUSR, },
+       { "/dev/ptmx",      5,  2, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH, },
+       { "/dev/rtc0",    252,  0, S_IFCHR|S_IRUSR|S_IWUSR, },
+       { NULL },
+};
 
-       return r;
-}
+static const struct pakfire_symlink {
+       const char* target;
+       const char* path;
+} symlinks[] = {
+       { "/proc/self/fd",   "/dev/fd", },
+       { "/proc/self/fd/0", "/dev/stdin" },
+       { "/proc/self/fd/1", "/dev/stdout" },
+       { "/proc/self/fd/2", "/dev/stderr" },
+       { "/proc/kcore",     "/dev/core" },
+       { NULL },
+};
 
 /*
        Easy way to iterate through all mountpoints
 */
 static int pakfire_mount_foreach(struct pakfire* pakfire, int direction,
                int (*callback)(struct pakfire* pakfire, struct libmnt_fs* fs, const void* data),
-               const char* option, const void* data) {
+               const void* data) {
        const char* root = pakfire_get_path(pakfire);
        int r = 1;
 
@@ -121,12 +134,6 @@ static int pakfire_mount_foreach(struct pakfire* pakfire, int direction,
                if (!pakfire_string_startswith(target, root))
                        continue;
 
-               // Filter by option
-               if (option) {
-                       if (!mnt_fs_match_options(fs, option))
-                               continue;
-               }
-
                // Call the callback for each relevant mountpoint
                r = callback(pakfire, fs, data);
                if (r)
@@ -154,7 +161,7 @@ static int __pakfire_is_mountpoint(struct pakfire* pakfire,
 
 int pakfire_is_mountpoint(struct pakfire* pakfire, const char* path) {
        return pakfire_mount_foreach(pakfire, MNT_ITER_FORWARD,
-               __pakfire_is_mountpoint, NULL, path);
+               __pakfire_is_mountpoint, path);
 }
 
 int pakfire_mount(struct pakfire* pakfire, const char* source, const char* target,
@@ -279,10 +286,48 @@ int pakfire_mount_list(struct pakfire* pakfire) {
        DEBUG(pakfire, "Mountpoints:\n");
 
        return pakfire_mount_foreach(pakfire, MNT_ITER_FORWARD,
-               __pakfire_mount_print, NULL, NULL);
+               __pakfire_mount_print, NULL);
+}
+
+static int pakfire_populate_dev(struct pakfire* pakfire) {
+       char path[PATH_MAX];
+
+       // Create device nodes
+       for (const struct pakfire_devnode* devnode = devnodes; devnode->path; devnode++) {
+               DEBUG(pakfire, "Creating device node %s\n", devnode->path);
+
+               int r = pakfire_make_path(pakfire, path, devnode->path);
+               if (r < 0)
+                       return 1;
+
+               dev_t dev = makedev(devnode->major, devnode->minor);
+
+               r = mknod(path, devnode->mode, dev);
+               if (r) {
+                       ERROR(pakfire, "Could not create %s: %m\n", devnode->path);
+                       return r;
+               }
+       }
+
+       // Create symlinks
+       for (const struct pakfire_symlink* s = symlinks; s->target; s++) {
+               DEBUG(pakfire, "Creating symlink %s -> %s\n", s->path, s->target);
+
+               int r = pakfire_make_path(pakfire, path, s->path);
+               if (r < 0)
+                       return 1;
+
+               r = symlink(s->target, path);
+               if (r) {
+                       ERROR(pakfire, "Could not create symlink %s: %m\n", s->path);
+                       return r;
+               }
+       }
+
+       return 0;
 }
 
-int pakfire_mount_all(struct pakfire* pakfire, const enum pakfire_mount_flags mount_flags) {
+int pakfire_mount_all(struct pakfire* pakfire) {
        char target[PATH_MAX];
        char options[PATH_MAX];
        int r;
@@ -290,41 +335,18 @@ int pakfire_mount_all(struct pakfire* pakfire, const enum pakfire_mount_flags mo
        // Fetch Pakfire's root directory
        const char* root = pakfire_get_path(pakfire);
 
-       // Are we being called from a new namespace?
-       const unsigned int in_new_ns = (mount_flags & MOUNT_IN_NEW_NS);
-
        for (const struct pakfire_mountpoint* mp = mountpoints; mp->source; mp++) {
-               if (!in_new_ns && (mp->mount_flags & MOUNT_IN_NEW_NS))
-                       continue;
-
-               if (in_new_ns && !(mp->mount_flags & MOUNT_IN_NEW_NS))
-                       continue;
-
                // Figure out where to mount
                r = pakfire_path_join(target, root, mp->target);
                if (r < 0)
                        return r;
 
-               // Append namespace mount option
-               if (in_new_ns) {
-                       if (mp->options)
-                               pakfire_string_format(options, "%s,%s",
-                                       mp->options, PAKFIRE_MOUNT_OPT_NAMESPACED);
-                       else
-                               pakfire_string_set(options, PAKFIRE_MOUNT_OPT_NAMESPACED);
-               } else {
-                       if (mp->options)
-                               pakfire_string_set(options, mp->options);
-                       else
-                               pakfire_string_set(options, "");
-               }
-
                // Create target
                pakfire_mkdir(target, 0);
 
 RETRY:
                // Perform mount()
-               r = pakfire_mount(pakfire, mp->source, target, mp->fstype, mp->flags, options);
+               r = pakfire_mount(pakfire, mp->source, target, mp->fstype, mp->flags, mp->options);
                if (r) {
                        // If the target directory does not exist, we will create it
                        if (errno == ENOENT) {
@@ -342,6 +364,11 @@ RETRY:
                }
        }
 
+       // Populate /dev
+       r = pakfire_populate_dev(pakfire);
+       if (r)
+               return r;
+
        return 0;
 }
 
@@ -357,7 +384,7 @@ static int __pakfire_umount(struct pakfire* pakfire,
 /*
        umounts everything that hasn't been umounted, yet
 */
-int pakfire_umount_all(struct pakfire* pakfire, const char* option) {
+int pakfire_umount_all(struct pakfire* pakfire) {
        return pakfire_mount_foreach(pakfire, MNT_ITER_BACKWARD,
-               __pakfire_umount, option, NULL);
+               __pakfire_umount, NULL);
 }
index b95815657363df695a25120a2393e00089c2af4c..6547bd811240e0702942f7f6e43b41277aa50de4 100644 (file)
@@ -28,7 +28,6 @@
 #include <sys/file.h>
 #include <sys/mount.h>
 #include <sys/stat.h>
-#include <sys/sysmacros.h>
 #include <sys/types.h>
 #include <syslog.h>
 #include <unistd.h>
@@ -147,75 +146,6 @@ int pakfire_on_root(struct pakfire* pakfire) {
        return (strcmp(pakfire->path, "/") == 0);
 }
 
-static const struct pakfire_devnode {
-       const char* path;
-       int major;
-       int minor;
-       mode_t mode;
-} devnodes[] = {
-       { "/dev/null",      1,  3, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH, },
-       { "/dev/zero",      1,  5, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH, },
-       { "/dev/full",      1,  7, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH, },
-       { "/dev/random",    1,  8, S_IFCHR|S_IRUSR|S_IRGRP|S_IROTH, },
-       { "/dev/urandom",   1,  9, S_IFCHR|S_IRUSR|S_IRGRP|S_IROTH, },
-       { "/dev/kmsg",      1, 11, S_IFCHR|S_IRUSR|S_IRGRP|S_IROTH, },
-       { "/dev/tty",       5,  0, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH, },
-       { "/dev/console",   5,  1, S_IFCHR|S_IRUSR|S_IWUSR, },
-       { "/dev/ptmx",      5,  2, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH, },
-       { "/dev/rtc0",    252,  0, S_IFCHR|S_IRUSR|S_IWUSR, },
-       { NULL },
-};
-
-static const struct pakfire_symlink {
-       const char* target;
-       const char* path;
-} symlinks[] = {
-       { "/proc/self/fd",   "/dev/fd", },
-       { "/proc/self/fd/0", "/dev/stdin" },
-       { "/proc/self/fd/1", "/dev/stdout" },
-       { "/proc/self/fd/2", "/dev/stderr" },
-       { "/proc/kcore",     "/dev/core" },
-       { NULL },
-};
-
-static int pakfire_populate_dev(struct pakfire* pakfire) {
-       char path[PATH_MAX];
-
-       // Create device nodes
-       for (const struct pakfire_devnode* devnode = devnodes; devnode->path; devnode++) {
-               DEBUG(pakfire, "Creating device node %s\n", devnode->path);
-
-               int r = pakfire_make_path(pakfire, path, devnode->path);
-               if (r < 0)
-                       return 1;
-
-               dev_t dev = makedev(devnode->major, devnode->minor);
-
-               r = mknod(path, devnode->mode, dev);
-               if (r) {
-                       ERROR(pakfire, "Could not create %s: %m\n", devnode->path);
-                       return r;
-               }
-       }
-
-       // Create symlinks
-       for (const struct pakfire_symlink* s = symlinks; s->target; s++) {
-               DEBUG(pakfire, "Creating symlink %s -> %s\n", s->path, s->target);
-
-               int r = pakfire_make_path(pakfire, path, s->path);
-               if (r < 0)
-                       return 1;
-
-               r = symlink(s->target, path);
-               if (r) {
-                       ERROR(pakfire, "Could not create symlink %s: %m\n", s->path);
-                       return r;
-               }
-       }
-
-       return 0;
-}
-
 static int log_priority(const char* priority) {
        char* end;
 
@@ -395,9 +325,6 @@ static void pakfire_free(struct pakfire* pakfire) {
        // Release lock (if not already done so)
        pakfire_release_lock(pakfire);
 
-       // umount everything
-       pakfire_umount_all(pakfire, 0);
-
        if (pakfire->destroy_on_free && *pakfire->path) {
                DEBUG(pakfire, "Destroying %s\n", pakfire->path);
 
@@ -838,16 +765,6 @@ PAKFIRE_EXPORT int pakfire_create(struct pakfire** pakfire, const char* path,
                goto ERROR;
        }
 
-       // Mount filesystems
-       r = pakfire_mount_all(p, 0);
-       if (r)
-               goto ERROR;
-
-       // Populate /dev
-       r = pakfire_populate_dev(p);
-       if (r)
-               goto ERROR;
-
        // Mount the interpreter (if needed)
        r = pakfire_mount_interpreter(p);
        if (r)