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;
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;
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
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
{ 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
*/