2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-09-02 07:15:31 +00:00

fs: Restore root

First of all, this should be done strictly after we've stopped accessing
files by their paths, even absolute. This place is right before going
into restorer.

And the second thing is that we want to re-use the open_fd_by_id engine,
since it handles various tricky cases of open-file-by-path. And since
there's no such thing as fchroot(int fd), we emulate it using the
/proc/self/fd/ links.

Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
Pavel Emelyanov
2013-09-25 13:46:01 +04:00
parent 75b1d4a1e3
commit c378f790b8
2 changed files with 40 additions and 9 deletions

View File

@@ -715,9 +715,6 @@ static int restore_one_alive_task(int pid, CoreEntry *core)
if (prepare_fds(current)) if (prepare_fds(current))
return -1; return -1;
if (prepare_fs(pid))
return -1;
if (prepare_file_locks(pid)) if (prepare_file_locks(pid))
return -1; return -1;
@@ -2563,6 +2560,14 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core)
task_args->clone_restore_fn = (void *)restore_thread_exec_start; task_args->clone_restore_fn = (void *)restore_thread_exec_start;
task_args->thread_args = thread_args; task_args->thread_args = thread_args;
/*
* Make root and cwd restore _that_ late not to break any
* attempts to open files by paths above (e.g. /proc).
*/
if (prepare_fs(pid))
goto err;
close_image_dir(); close_image_dir();
__gcov_flush(); __gcov_flush();

38
files.c
View File

@@ -938,6 +938,20 @@ out:
return ret; return ret;
} }
static int fchroot(int fd)
{
char fd_path[32];
/*
* There's no such thing in syscalls. We can emulate
* it using the /proc/self/fd/ :)
*/
sprintf(fd_path, "/proc/self/fd/%d", fd);
pr_debug("Going to chroot into %s\n", fd_path);
return chroot(fd_path);
}
int prepare_fs(int pid) int prepare_fs(int pid)
{ {
int ifd, dd, ret = -1; int ifd, dd, ret = -1;
@@ -950,6 +964,10 @@ int prepare_fs(int pid)
if (pb_read_one(ifd, &fe, PB_FS) < 0) if (pb_read_one(ifd, &fe, PB_FS) < 0)
goto out_i; goto out_i;
/*
* Restore CWD
*/
dd = open_reg_by_id(fe->cwd_id); dd = open_reg_by_id(fe->cwd_id);
if (dd < 0) { if (dd < 0) {
pr_err("Can't open cwd %#x\n", fe->cwd_id); pr_err("Can't open cwd %#x\n", fe->cwd_id);
@@ -964,14 +982,22 @@ int prepare_fs(int pid)
} }
/* /*
* FIXME: restore task's root. Don't want to do it now, since * Restore root
* it's not yet clean how we're going to resolve tasks' paths
* relative to the dumper/restorer and all this logic is likely
* to be hidden in a couple of calls (open_fe_fd is one od them)
* but for chroot there's no fchroot call, we have to chroot
* by path thus exposing this (yet unclean) logic here.
*/ */
dd = open_reg_by_id(fe->root_id);
if (dd < 0) {
pr_err("Can't open root %#x\n", fe->root_id);
goto err;
}
ret = fchroot(dd);
close(dd);
if (ret < 0) {
pr_perror("Can't change root");
goto err;
}
if (fe->has_umask) { if (fe->has_umask) {
pr_info("Restoring umask to %o\n", fe->umask); pr_info("Restoring umask to %o\n", fe->umask);
umask(fe->umask); umask(fe->umask);