[CRIU] [PATCH 5/6] restore: Do fchroot() via proc helpers

Pavel Emelyanov xemul at parallels.com
Thu Jun 5 09:18:41 PDT 2014


There's no such thing as fchroot() in Linux, but we need to do
chroot() into existing file descriptor. Before this patch we did
this by chroot()-ing into /proc/self/fd/$fd. W/o proc mounted it's
no longer possible, so do this like

fchdir(proc_service_fd);
chroot("./self/fd/$root_fd");
fchdir($cwd_fd);

Thanks to Andrey Vagin for this trick ;)

Signed-off-by: Pavel Emelyanov <xemul at parallels.com>

---
 files.c | 32 +++++++++++++++++++++-----------
 1 file changed, 21 insertions(+), 11 deletions(-)

diff --git a/files.c b/files.c
index 96f0330..991d4a2 100644
--- a/files.c
+++ b/files.c
@@ -997,13 +997,23 @@ out:
 static int fchroot(int fd)
 {
 	char fd_path[PSFDS];
+	int proc;
 
 	/*
 	 * There's no such thing in syscalls. We can emulate
 	 * it using the /proc/self/fd/ :)
+	 *
+	 * But since there might be no /proc mount in our mount
+	 * namespace, we will have to ... workaround it.
 	 */
 
-	sprintf(fd_path, "/proc/self/fd/%d", fd);
+	proc = get_service_fd(PROC_FD_OFF);
+	if (fchdir(proc) < 0) {
+		pr_perror("Can't chdir to proc");
+		return -1;
+	}
+
+	sprintf(fd_path, "./self/fd/%d", fd);
 	pr_debug("Going to chroot into %s\n", fd_path);
 	return chroot(fd_path);
 }
@@ -1021,36 +1031,36 @@ int prepare_fs(int pid)
 		goto out_i;
 
 	/*
-	 * Restore CWD
+	 * Restore root
 	 */
 
-	dd = open_reg_by_id(fe->cwd_id);
+	dd = open_reg_by_id(fe->root_id);
 	if (dd < 0) {
-		pr_err("Can't open cwd %#x\n", fe->cwd_id);
+		pr_err("Can't open root %#x\n", fe->root_id);
 		goto err;
 	}
 
-	ret = fchdir(dd);
+	ret = fchroot(dd);
 	close(dd);
 	if (ret < 0) {
-		pr_perror("Can't change cwd");
+		pr_perror("Can't change root");
 		goto err;
 	}
 
 	/*
-	 * Restore root
+	 * Restore CWD
 	 */
 
-	dd = open_reg_by_id(fe->root_id);
+	dd = open_reg_by_id(fe->cwd_id);
 	if (dd < 0) {
-		pr_err("Can't open root %#x\n", fe->root_id);
+		pr_err("Can't open cwd %#x\n", fe->cwd_id);
 		goto err;
 	}
 
-	ret = fchroot(dd);
+	ret = fchdir(dd);
 	close(dd);
 	if (ret < 0) {
-		pr_perror("Can't change root");
+		pr_perror("Can't change cwd");
 		goto err;
 	}
 
-- 
1.8.4.2


More information about the CRIU mailing list