]> git.ipfire.org Git - pakfire.git/commitdiff
libpakfire: Add pakfire_activate/deactivate
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 12 Feb 2021 19:23:01 +0000 (19:23 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 12 Feb 2021 19:23:01 +0000 (19:23 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/execute.c
src/libpakfire/include/pakfire/pakfire.h
src/libpakfire/libpakfire.sym
src/libpakfire/pakfire.c
src/pakfire/builder.py
tests/libpakfire/main.c

index 029d80b6a10a3399ecb03945c0f2daa30d07518b..1e4de1e75ce04a03a692b0e3201eb5fb38f183da 100644 (file)
@@ -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);
 
index a8d17931a7661461669bebac133cf25a84878d3a..c433cda48bcb4bf2a15ab97911517fefd502dc20 100644 (file)
@@ -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);
index 86a7b6249af8d389d76c4ff1170d0da820af6e86..e69f8861cb44fdb0adce6e04490bf9bd696e6a34 100644 (file)
 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;
index d78ddb2c1fb50bb4fb3c693b5937acc905c5d0a0..e85cc2c358cec3bfb10d5c6759edd67eb14584b4 100644 (file)
@@ -24,6 +24,7 @@
 #include <stddef.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <sys/mount.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <syslog.h>
@@ -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;
 }
index f60a6b8ef9563abb962dfc07149189ec146b19e6..2220943dc16c9633734857325d0b9388a009c50c 100644 (file)
@@ -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.
index ccb1fbdb870b8a3628f0dff380976701ddf5d115..ce508982cbe209d619f83b70b107bd5a060d017c 100644 (file)
@@ -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();
 }