From: Michael Tremer Date: Sat, 21 May 2022 14:15:05 +0000 (+0000) Subject: execute: Use pivot_root instead of chroot X-Git-Tag: 0.9.28~765 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c9558408cce6191c39780f28fa987ac79b48505b;p=pakfire.git execute: Use pivot_root instead of chroot Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/execute.c b/src/libpakfire/execute.c index b4aab537e..082b04be9 100644 --- a/src/libpakfire/execute.c +++ b/src/libpakfire/execute.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -82,6 +83,10 @@ struct pakfire_execute_buffer { #define __NR_clone3 435 #endif +static int pivot_root(const char* new_root, const char* put_old) { + return syscall(__NR_pivot_root, new_root, put_old); +} + static int pakfire_execute_buffer_is_full(const struct pakfire_execute_buffer* buffer) { return (sizeof(buffer->data) == buffer->used); } @@ -534,12 +539,15 @@ static int set_environ(struct pakfire_execute* env, const char* key, const char* static int pakfire_execute_fork(void* data) { struct pakfire_execute* env = (struct pakfire_execute*)data; + int r; struct pakfire* pakfire = env->pakfire; const char* root = pakfire_get_path(pakfire); const char* arch = pakfire_get_arch(pakfire); + char oldroot[PATH_MAX]; + DEBUG(pakfire, "Execution environment has been forked as PID %d\n", getpid()); DEBUG(pakfire, " root : %s\n", root); DEBUG(pakfire, " cgroup : %s\n", env->cgroup); @@ -552,23 +560,53 @@ static int pakfire_execute_fork(void* data) { // Change root (unless root is /) if (strcmp(root, "/") != 0) { - int r = chroot(root); + r = pakfire_string_format(oldroot, "%s/.oldroot.XXXXXX", root); + if (r < 0) { + ERROR(pakfire, "Could not figure out where the old root directory is going: %m\n"); + return r; + } + + // Create temporary directory + if (!pakfire_mkdtemp(oldroot)) { + ERROR(pakfire, "Could not create temporary directory: %m\n"); + return r; + } + + // Call pivot_root() + r = pivot_root(root, oldroot); if (r) { - ERROR(pakfire, "chroot() to %s failed: %m\n", root); + ERROR(pakfire, "pivot_root() to %s failed: %m\n", root); return 1; } + // Change directory to / r = chdir("/"); if (r) { ERROR(pakfire, "chdir() after chroot() failed: %m\n"); return 1; } + + const char* __oldroot = oldroot + strlen(root); + + // Umount the old root directory + r = umount2(__oldroot, MNT_DETACH); + if (r) { + ERROR(pakfire, "Could not umount old root directory: %m\n"); + return r; + } + + // Remove the old root directory + r = rmdir(__oldroot); + if (r) { + ERROR(pakfire, "Could not remove the old root directory: %m\n"); + return r; + } } // Set personality unsigned long persona = pakfire_arch_personality(arch); if (persona) { - int r = personality(persona); + r = personality(persona); if (r < 0) { ERROR(pakfire, "Could not set personality (%x)\n", (unsigned int)persona); @@ -598,7 +636,7 @@ static int pakfire_execute_fork(void* data) { } // Reset open file limit (http://0pointer.net/blog/file-descriptor-limits.html) - int r = pakfire_rlimit_reset_nofile(pakfire); + r = pakfire_rlimit_reset_nofile(pakfire); if (r) return r; diff --git a/src/libpakfire/pakfire.c b/src/libpakfire/pakfire.c index 744793887..ea7bf2deb 100644 --- a/src/libpakfire/pakfire.c +++ b/src/libpakfire/pakfire.c @@ -218,6 +218,13 @@ static int pakfire_mount(struct pakfire* pakfire) { char target[PATH_MAX]; int r; + // Remount / as private + r = mount(NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL); + if (r) { + ERROR(pakfire, "Could not re-mount / as private: %m\n"); + return r; + } + for (const struct pakfire_mountpoint* mp = mountpoints; mp->source; mp++) { // Skip mounting root when a directory has been passed if (!*mp->target && !pakfire->mount_tmpfs)