diff --git a/crun.1.md b/crun.1.md index 27a3cef1e8..65c3f0552d 100644 --- a/crun.1.md +++ b/crun.1.md @@ -90,6 +90,10 @@ If no backend is specified, then *file:* is used by default. Define the format of the log messages. It can either be **text**, or **json**. The default is **text**. +**--no-pivot** +Use `chroot(2)` instead of `pivot_root(2)` when creating the container. +This option is not safe, and should be avoided. + **--root**=**DIR** Defines where to store the state for crun containers. diff --git a/src/create.c b/src/create.c index ae414191e1..1a0dacb5be 100644 --- a/src/create.c +++ b/src/create.c @@ -34,7 +34,8 @@ enum OPTION_PID_FILE, OPTION_NO_SUBREAPER, OPTION_NO_NEW_KEYRING, - OPTION_PRESERVE_FDS + OPTION_PRESERVE_FDS, + OPTION_NO_PIVOT }; static const char *bundle = NULL; @@ -46,6 +47,7 @@ static struct argp_option options[] = {"bundle", 'b', 0, 0, "container bundle (default \".\")" }, {"console-socket", OPTION_CONSOLE_SOCKET, "SOCKET", 0, "path to a socket that will receive the master end of the tty" }, {"preserve-fds", OPTION_PRESERVE_FDS, 0, 0, "pass additional FDs to the container"}, + {"no-pivot", OPTION_NO_PIVOT, 0, 0, "do not use pivot_root"}, {"pid-file", OPTION_PID_FILE, "FILE", 0, "where to write the PID of the container"}, {"no-subreaper", OPTION_NO_SUBREAPER, 0, 0, "do not create a subreaper process"}, {"no-new-keyring", OPTION_NO_NEW_KEYRING, 0, 0, "keep the same session key"}, @@ -77,6 +79,10 @@ parse_opt (int key, char *arg, struct argp_state *state) crun_context.no_subreaper = true; break; + case OPTION_NO_PIVOT: + crun_context.no_pivot = true; + break; + case OPTION_NO_NEW_KEYRING: crun_context.no_new_keyring = true; break; diff --git a/src/libcrun/container.c b/src/libcrun/container.c index 67692eb7ac..2fc640e30d 100644 --- a/src/libcrun/container.c +++ b/src/libcrun/container.c @@ -496,7 +496,7 @@ container_entrypoint_init (void *args, const char *notify_socket, if (UNLIKELY (ret < 0)) return ret; - ret = libcrun_do_pivot_root (container, rootfs, err); + ret = libcrun_do_pivot_root (container, entrypoint_args->context->no_pivot, rootfs, err); if (UNLIKELY (ret < 0)) return ret; diff --git a/src/libcrun/container.h b/src/libcrun/container.h index ebfe9a119f..079d3b61f3 100644 --- a/src/libcrun/container.h +++ b/src/libcrun/container.h @@ -43,6 +43,7 @@ struct libcrun_context_s bool no_subreaper; bool no_new_keyring; bool force_no_cgroup; + bool no_pivot; }; enum diff --git a/src/libcrun/linux.c b/src/libcrun/linux.c index c6dcb94e58..e770c0ebd7 100644 --- a/src/libcrun/linux.c +++ b/src/libcrun/linux.c @@ -1193,15 +1193,56 @@ libcrun_set_mounts (libcrun_container_t *container, const char *rootfs, libcrun_ return 0; } +static int +move_root (libcrun_container_t *container, const char *rootfs, libcrun_error_t *err) +{ + int ret; + + ret = chdir (rootfs); + if (UNLIKELY (ret < 0)) + return crun_make_error (err, errno, "chdir to '%s'", rootfs); + + ret = umount2 ("/sys", MNT_DETACH); + if (UNLIKELY (ret < 0)) + return crun_make_error (err, errno, "umount /sys"); + + ret = umount2 ("/proc", MNT_DETACH); + if (UNLIKELY (ret < 0)) + return crun_make_error (err, errno, "umount /proc"); + + ret = mount (rootfs, "/", "", MS_MOVE, ""); + if (UNLIKELY (ret < 0)) + return crun_make_error (err, errno, "mount MS_MOVE to '/'"); + + ret = chroot ("."); + if (UNLIKELY (ret < 0)) + return crun_make_error (err, errno, "chroot to '%s'", rootfs); + + ret = chdir ("/"); + if (UNLIKELY (ret < 0)) + return crun_make_error (err, errno, "chdir to '%s'", rootfs); + + return 0; +} + int -libcrun_do_pivot_root (libcrun_container_t *container, const char *rootfs, libcrun_error_t *err) +libcrun_do_pivot_root (libcrun_container_t *container, bool no_pivot, const char *rootfs, libcrun_error_t *err) { int ret; if (get_private_data (container)->unshare_flags & CLONE_NEWNS) { - ret = do_pivot (container, rootfs, err); - if (UNLIKELY (ret < 0)) - return ret; + if (no_pivot) + { + ret = move_root (container, rootfs, err); + if (UNLIKELY (ret < 0)) + return ret; + } + else + { + ret = do_pivot (container, rootfs, err); + if (UNLIKELY (ret < 0)) + return ret; + } ret = do_mount (container, "", "/", "", get_private_data (container)->rootfs_propagation, "", 0, err); if (UNLIKELY (ret < 0)) diff --git a/src/libcrun/linux.h b/src/libcrun/linux.h index d84c019ee6..ea05ff21ff 100644 --- a/src/libcrun/linux.h +++ b/src/libcrun/linux.h @@ -39,7 +39,7 @@ pid_t libcrun_run_linux_container (libcrun_container_t *container, libcrun_error_t *err); int get_notify_fd (libcrun_context_t *context, libcrun_container_t *container, int *notify_socket_out, libcrun_error_t *err); int libcrun_set_mounts (libcrun_container_t *container, const char *rootfs, libcrun_error_t *err); -int libcrun_do_pivot_root (libcrun_container_t *container, const char *rootfs, libcrun_error_t *err); +int libcrun_do_pivot_root (libcrun_container_t *container, bool no_pivot, const char *rootfs, libcrun_error_t *err); int libcrun_set_usernamespace (libcrun_container_t *container, pid_t pid, libcrun_error_t *err); int libcrun_set_caps (oci_container_process_capabilities *capabilities, uid_t uid, gid_t gid, int no_new_privileges, libcrun_error_t *err); int libcrun_set_rlimits (oci_container_process_rlimits_element **rlimits, size_t len, libcrun_error_t *err); diff --git a/src/run.c b/src/run.c index e1e4a79392..3cf2795d1a 100644 --- a/src/run.c +++ b/src/run.c @@ -36,7 +36,8 @@ enum OPTION_PID_FILE, OPTION_NO_SUBREAPER, OPTION_NO_NEW_KEYRING, - OPTION_PRESERVE_FDS + OPTION_PRESERVE_FDS, + OPTION_NO_PIVOT }; static const char *bundle = NULL; @@ -52,6 +53,7 @@ static struct argp_option options[] = {"pid-file", OPTION_PID_FILE, "FILE", 0, "where to write the PID of the container"}, {"no-subreaper", OPTION_NO_SUBREAPER, 0, 0, "do not create a subreaper process"}, {"no-new-keyring", OPTION_NO_NEW_KEYRING, 0, 0, "keep the same session key"}, + {"no-pivot", OPTION_NO_PIVOT, 0, 0, "do not use pivot_root"}, { 0 } }; @@ -90,6 +92,10 @@ parse_opt (int key, char *arg, struct argp_state *state) crun_context.pid_file = argp_mandatory_argument (arg, state); break; + case OPTION_NO_PIVOT: + crun_context.no_pivot = true; + break; + case ARGP_KEY_NO_ARGS: libcrun_fail_with_error (0, "please specify a ID for the container");