#include <string.h>
#include <sys/capability.h>
#include <sys/epoll.h>
+#include <sys/mount.h>
#include <sys/personality.h>
#include <sys/prctl.h>
#include <sys/types.h>
#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);
}
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);
// 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);
}
// 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;