]> git.ipfire.org Git - pakfire.git/commitdiff
jail: Use pivot_root() again instead of chroot()
authorMichael Tremer <michael.tremer@ipfire.org>
Mon, 17 Jul 2023 16:44:50 +0000 (16:44 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Mon, 17 Jul 2023 16:44:50 +0000 (16:44 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/include/pakfire/mount.h
src/libpakfire/jail.c
src/libpakfire/mount.c

index 39e8750b3546ba81f7b9bbfa7c234dd132479a4c..11638578f2723f8a35530613e1cf67110e276f9a 100644 (file)
@@ -25,6 +25,8 @@
 
 #include <pakfire/pakfire.h>
 
+int pakfire_mount_make_mounpoint(struct pakfire* pakfire, const char* path);
+
 int pakfire_bind(struct pakfire* pakfire, const char* src, const char* dst, int flags);
 
 int pakfire_mount_list(struct pakfire* pakfire);
index af7de97dc0ba5bbcbb026888b35f49d4ea102425..db37cf7df80ed84642b0ba559e8a4039d8aea1f8 100644 (file)
@@ -172,6 +172,10 @@ static int pidfd_send_signal(int pidfd, int sig, siginfo_t* info, unsigned int f
        return syscall(SYS_pidfd_send_signal, pidfd, sig, info, flags);
 }
 
+static int pivot_root(const char* new_root, const char* old_root) {
+       return syscall(SYS_pivot_root, new_root, old_root);
+}
+
 static int pakfire_jail_exec_has_flag(
                const struct pakfire_jail_exec* ctx, const enum pakfire_jail_exec_flags flag) {
        return ctx->flags & flag;
@@ -1555,6 +1559,33 @@ static int pakfire_jail_parent(struct pakfire_jail* jail, struct pakfire_jail_ex
        return 0;
 }
 
+static int pakfire_jail_switch_root(struct pakfire_jail* jail, const char* root) {
+       int r;
+
+       // Change to the new root
+       r = chdir(root);
+       if (r) {
+               ERROR(jail->pakfire, "chdir(%s) failed: %m\n", root);
+               return r;
+       }
+
+       // Switch Root!
+       r = pivot_root(".", ".");
+       if (r) {
+               ERROR(jail->pakfire, "Failed changing into the new root directory %s: %m\n", root);
+               return r;
+       }
+
+       // Umount the old root
+       r = umount2(".", MNT_DETACH);
+       if (r) {
+               ERROR(jail->pakfire, "Could not umount the old root filesystem: %m\n");
+               return r;
+       }
+
+       return 0;
+}
+
 static int pakfire_jail_child(struct pakfire_jail* jail, struct pakfire_jail_exec* ctx,
                const char* argv[]) {
        int r;
@@ -1601,6 +1632,11 @@ static int pakfire_jail_child(struct pakfire_jail* jail, struct pakfire_jail_exe
        const char* root = pakfire_get_path(jail->pakfire);
        const char* arch = pakfire_get_arch(jail->pakfire);
 
+       // Make root a mountpoint in the new mount namespace
+       r = pakfire_mount_make_mounpoint(jail->pakfire, root);
+       if (r)
+               return r;
+
        // Change root (unless root is /)
        if (!pakfire_on_root(jail->pakfire)) {
                // Mount everything
@@ -1608,19 +1644,10 @@ static int pakfire_jail_child(struct pakfire_jail* jail, struct pakfire_jail_exe
                if (r)
                        return r;
 
-               // Call chroot()
-               r = chroot(root);
-               if (r) {
-                       ERROR(jail->pakfire, "chroot() to %s failed: %m\n", root);
-                       return 1;
-               }
-
-               // Change directory to /
-               r = chdir("/");
-               if (r) {
-                       ERROR(jail->pakfire, "chdir() after chroot() failed: %m\n");
-                       return 1;
-               }
+               // chroot()
+               r = pakfire_jail_switch_root(jail, root);
+               if (r)
+                       return r;
        }
 
        // Set personality
index 9dd4af17d4953a6e12bc1ec8c71895c792fab28c..1983cea3ab8192afea2b72b0ba74bb33675c3a6c 100644 (file)
@@ -143,6 +143,40 @@ static const struct pakfire_symlink {
        { NULL },
 };
 
+static int pakfire_mount_is_mountpoint(struct pakfire* pakfire, const char* path) {
+       // XXX THIS STILL NEEDS TO BE IMPLEMENTED
+       return 1;
+}
+
+int pakfire_mount_make_mounpoint(struct pakfire* pakfire, const char* path) {
+       int r;
+
+       // Check if path already is a mountpoint
+       r = pakfire_mount_is_mountpoint(pakfire, path);
+       switch (r) {
+               // Already is a mountpoint
+               case 0:
+                       return 0;
+
+               // Is not a mountpoint
+               case 1:
+                       break;
+
+               default:
+                       ERROR(pakfire, "Could not determine whether %s is a mountpoint: %m\n", path);
+                       return r;
+       }
+
+       // Bind-mount to self
+       r = mount(path, path, NULL, MS_BIND|MS_REC, NULL);
+       if (r) {
+               ERROR(pakfire, "Could not make %s a mountpoint: %m\n", path);
+               return r;
+       }
+
+       return 0;
+}
+
 /*
        Easy way to iterate through all mountpoints
 */