From: Michael Tremer Date: Sun, 17 Jul 2022 18:16:04 +0000 (+0000) Subject: execute: Mount all file systems only in namespace X-Git-Tag: 0.9.28~694 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f71c82d89a3b757ebe49262b18467db6d065e18d;p=pakfire.git execute: Mount all file systems only in namespace 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 --- diff --git a/src/libpakfire/execute.c b/src/libpakfire/execute.c index 1780b3436..27a07aae0 100644 --- a/src/libpakfire/execute.c +++ b/src/libpakfire/execute.c @@ -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++) diff --git a/src/libpakfire/include/pakfire/mount.h b/src/libpakfire/include/pakfire/mount.h index fba1ae735..20330e08c 100644 --- a/src/libpakfire/include/pakfire/mount.h +++ b/src/libpakfire/include/pakfire/mount.h @@ -24,18 +24,12 @@ #include -#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 */ diff --git a/src/libpakfire/mount.c b/src/libpakfire/mount.c index 67313d446..f7b1b966a 100644 --- a/src/libpakfire/mount.c +++ b/src/libpakfire/mount.c @@ -23,6 +23,7 @@ #include #include #include +#include #include // 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, 0 }, - { "/sys", "sys", "bind", MS_BIND|MS_RDONLY|MS_REMOUNT, NULL, 0 }, + { "/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", 0 }, - { "/dev/pts", "dev/pts", "bind", MS_BIND, NULL, 0 }, + "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", 0 }, + "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); } diff --git a/src/libpakfire/pakfire.c b/src/libpakfire/pakfire.c index b95815657..6547bd811 100644 --- a/src/libpakfire/pakfire.c +++ b/src/libpakfire/pakfire.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -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)