From 701f883765e46ec176bec49c730d747d6ca357ac Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Thu, 5 Jun 2014 20:18:41 +0400 Subject: [PATCH] restore: Do fchroot() via proc helpers 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 Acked-by: Andrew Vagin --- files.c | 46 ++++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/files.c b/files.c index 96f0330f9..991d4a237 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); } @@ -1020,23 +1030,6 @@ int prepare_fs(int pid) if (pb_read_one(ifd, &fe, PB_FS) < 0) goto out_i; - /* - * Restore CWD - */ - - dd = open_reg_by_id(fe->cwd_id); - if (dd < 0) { - pr_err("Can't open cwd %#x\n", fe->cwd_id); - goto err; - } - - ret = fchdir(dd); - close(dd); - if (ret < 0) { - pr_perror("Can't change cwd"); - goto err; - } - /* * Restore root */ @@ -1054,6 +1047,23 @@ int prepare_fs(int pid) goto err; } + /* + * Restore CWD + */ + + dd = open_reg_by_id(fe->cwd_id); + if (dd < 0) { + pr_err("Can't open cwd %#x\n", fe->cwd_id); + goto err; + } + + ret = fchdir(dd); + close(dd); + if (ret < 0) { + pr_perror("Can't change cwd"); + goto err; + } + if (fe->has_umask) { pr_info("Restoring umask to %o\n", fe->umask); umask(fe->umask);