From: Michael Tremer Date: Fri, 12 Feb 2021 19:23:01 +0000 (+0000) Subject: libpakfire: Add pakfire_activate/deactivate X-Git-Tag: 0.9.28~1285^2~743 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6ef698ea9d1b425a3cc341ed18bb75d87a1a3653;p=pakfire.git libpakfire: Add pakfire_activate/deactivate Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/execute.c b/src/libpakfire/execute.c index 029d80b6a..1e4de1e75 100644 --- a/src/libpakfire/execute.c +++ b/src/libpakfire/execute.c @@ -362,16 +362,22 @@ PAKFIRE_EXPORT int pakfire_execute(Pakfire pakfire, const char* argv[], char* en } } + // Activate + int r = pakfire_activate(pakfire); + if (r) + return r; + // Fork this process pid_t pid = clone(pakfire_execute_fork, stack + sizeof(stack), cflags, &env); if (pid < 0) { ERROR(pakfire, "Could not fork: %s\n", strerror(errno)); + pakfire_deactivate(pakfire); return -errno; } // Set some useful error code - int r = -ESRCH; + r = -ESRCH; int status = 0; DEBUG(pakfire, "Waiting for PID %d to finish its work\n", pid); @@ -391,6 +397,9 @@ PAKFIRE_EXPORT int pakfire_execute(Pakfire pakfire, const char* argv[], char* en if (!status) waitpid(pid, &status, 0); + // Deactivate + pakfire_deactivate(pakfire); + if (WIFEXITED(status)) { r = WEXITSTATUS(status); diff --git a/src/libpakfire/include/pakfire/pakfire.h b/src/libpakfire/include/pakfire/pakfire.h index a8d17931a..c433cda48 100644 --- a/src/libpakfire/include/pakfire/pakfire.h +++ b/src/libpakfire/include/pakfire/pakfire.h @@ -35,6 +35,10 @@ Pakfire pakfire_unref(Pakfire pakfire); const char* pakfire_get_path(Pakfire pakfire); char* pakfire_make_path(Pakfire pakfire, const char* path); + +int pakfire_activate(Pakfire pakfire); +int pakfire_deactivate(Pakfire pakfire); + const char* pakfire_get_arch(Pakfire pakfire); const char** pakfire_get_installonly(Pakfire pakfire); diff --git a/src/libpakfire/libpakfire.sym b/src/libpakfire/libpakfire.sym index 86a7b6249..e69f8861c 100644 --- a/src/libpakfire/libpakfire.sym +++ b/src/libpakfire/libpakfire.sym @@ -21,10 +21,12 @@ LIBPAKFIRE_0 { global: # pakfire + pakfire_activate; pakfire_cache_age; pakfire_cache_stat; pakfire_count_packages; pakfire_create; + pakfire_deactivate; pakfire_execute; pakfire_execute_command; pakfire_get_arch; diff --git a/src/libpakfire/pakfire.c b/src/libpakfire/pakfire.c index d78ddb2c1..e85cc2c35 100644 --- a/src/libpakfire/pakfire.c +++ b/src/libpakfire/pakfire.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -249,6 +250,136 @@ PAKFIRE_EXPORT char* pakfire_make_path(Pakfire pakfire, const char* path) { return pakfire_path_join(pakfire->path, path); } +static const struct pakfire_mountpoint { + const char* source; + const char* target; + const char* fstype; + int flags; + const char* options; +} mountpoints[] = { + { "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", NULL, MS_BIND, NULL }, + { "/proc/sys/net", "proc/sys/net", NULL, MS_BIND, NULL }, + { "/proc/sys", "proc/sys", NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, NULL }, + + // Bind mount /sys as read-only + { "/sys", "sys", NULL, MS_BIND, NULL }, + { "/sys", "sys", NULL, 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", NULL, MS_BIND, NULL }, + + // Create a new /run + { "pakfire_tmpfs", "run", "tmpfs", MS_NOSUID|MS_NOEXEC|MS_NODEV, + "mode=755,size=4m,nr_inodes=1k" }, + + // Create a new /tmp + { "pakfire_tmpfs", "tmp", "tmpfs", MS_NOSUID|MS_NOEXEC|MS_NODEV, + "mode=755" }, + + // The end + { NULL }, +}; + +static int pakfire_mount(Pakfire pakfire) { + int r; + + for (const struct pakfire_mountpoint* mp = mountpoints; mp->source; mp++) { + DEBUG(pakfire, "Mounting /%s\n", mp->target); + + char* target = pakfire_path_join(pakfire->path, mp->target); + +RETRY: + // Perform mount() + r = mount(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) { + r = pakfire_mkdir(pakfire, target, S_IRUSR|S_IWUSR|S_IXUSR); + if (r) { + ERROR(pakfire, "Could not create %s\n", target); + free(target); + return r; + } + + goto RETRY; + } + + ERROR(pakfire, "Could not mount /%s: %s\n", mp->target, strerror(errno)); + free(target); + return r; + } + + free(target); + } + + return 0; +} + +static int pakfire_umount(Pakfire pakfire) { + // Offset to the last element in mountpoints + const size_t s = (sizeof(mountpoints) / sizeof(*mountpoints)) - 1; + char* target = NULL; + int r = 0; + + // Walk through the array backwards + for (const struct pakfire_mountpoint* mp = mountpoints + s; mp-- != mountpoints;) { + DEBUG(pakfire, "Umounting /%s\n", mp->target); + int flags = 0; + + target = pakfire_path_join(pakfire->path, mp->target); + +RETRY: + // Perform umount + r = umount2(target, flags); + + if (r) { + // Skip anything that wasn't mounted + if (errno == EINVAL) + continue; + + // Attempt a laze umount when busy + else if (errno == EBUSY) { + flags |= MNT_DETACH; + goto RETRY; + } + + ERROR(pakfire, "Could not umount %s: %s\n", mp->target, strerror(errno)); + goto ERROR; + } + } + +ERROR: + if (target) + free(target); + + return r; +} + +PAKFIRE_EXPORT int pakfire_activate(Pakfire pakfire) { + if (strcmp(pakfire->path, "/") == 0) + return 0; + + // Mount filesystems + int r = pakfire_mount(pakfire); + if (r) { + pakfire_umount(pakfire); + + return r; + } + + return 0; +} + +PAKFIRE_EXPORT int pakfire_deactivate(Pakfire pakfire) { + return pakfire_umount(pakfire); +} + PAKFIRE_EXPORT const char* pakfire_get_arch(Pakfire pakfire) { return pakfire->arch; } diff --git a/src/pakfire/builder.py b/src/pakfire/builder.py index f60a6b8ef..2220943dc 100644 --- a/src/pakfire/builder.py +++ b/src/pakfire/builder.py @@ -221,26 +221,6 @@ class Builder(object): ("pakfire_root", "/", "tmpfs", "defaults"), ] - mountpoints += [ - # src, dest, fs, options - ("pakfire_proc", "/proc", "proc", "nosuid,noexec,nodev"), - ("/proc/sys", "/proc/sys", "bind", "bind"), - ("/proc/sys", "/proc/sys", "bind", "bind,ro,remount"), - ("/sys", "/sys", "bind", "bind"), - ("/sys", "/sys", "bind", "bind,ro,remount"), - ("pakfire_tmpfs", "/dev", "tmpfs", "mode=755,nosuid"), - ("/dev/pts", "/dev/pts", "bind", "bind"), - ("pakfire_tmpfs", "/run", "tmpfs", "mode=755,nosuid,nodev"), - ("pakfire_tmpfs", "/tmp", "tmpfs", "mode=755,nosuid,nodev"), - ] - - # If selinux is enabled. - if os.path.exists("/sys/fs/selinux"): - mountpoints += [ - ("/sys/fs/selinux", "/sys/fs/selinux", "bind", "bind"), - ("/sys/fs/selinux", "/sys/fs/selinux", "bind", "bind,ro,remount"), - ] - # If ccache support is requested, we bind mount the cache. if self.settings.get("enable_ccache"): # Create ccache cache directory if it does not exist. diff --git a/tests/libpakfire/main.c b/tests/libpakfire/main.c index ccb1fbdb8..ce508982c 100644 --- a/tests/libpakfire/main.c +++ b/tests/libpakfire/main.c @@ -35,9 +35,20 @@ static int test_path(const struct test* t) { return EXIT_SUCCESS; } +static int test_activate(const struct test* t) { + int r = pakfire_activate(t->pakfire); + ASSERT(r == 0); + + r = pakfire_deactivate(t->pakfire); + ASSERT(r == 0); + + return 0; +} + int main(int argc, char** argv) { testsuite_add_test(test_init); testsuite_add_test(test_path); + testsuite_add_test(test_activate); return testsuite_run(); }