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

Filipe Brandenburger filbranden at google.com
Thu Jun 5 09:26:27 PDT 2014


In fchroot(), if fchdir() succeeds but then chroot() fails, it will
have the unwanted side effect of leaving you in a different directory
than you were before... Is that a problem?

On Thu, Jun 5, 2014 at 9:18 AM, Pavel Emelyanov <xemul at parallels.com> wrote:
> 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
> _______________________________________________
> CRIU mailing list
> CRIU at openvz.org
> https://lists.openvz.org/mailman/listinfo/criu


More information about the CRIU mailing list