diff --git a/configure.ac b/configure.ac index 280aa8023..a14b2029d 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ([2.69]) -AC_INIT([crun], [0.10.4], [giuseppe@scrivano.org]) +AC_INIT([crun], [0.10.5], [giuseppe@scrivano.org]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_MACRO_DIR([m4]) diff --git a/src/libcrun/cgroup.c b/src/libcrun/cgroup.c index 3b7ec907f..ec966a913 100644 --- a/src/libcrun/cgroup.c +++ b/src/libcrun/cgroup.c @@ -310,7 +310,7 @@ enter_cgroup_subsystem (pid_t pid, const char *subsystem, const char *path, int xasprintf (&cgroup_path, "/sys/fs/cgroup/%s%s", subsystem, path ? path : ""); if (ensure_missing) { - ret = crun_ensure_directory (cgroup_path, 0755, err); + ret = crun_ensure_directory (cgroup_path, 0755, false, err); if (UNLIKELY (ret < 0)) { if (errno != EROFS) @@ -461,7 +461,7 @@ enter_cgroup (int cgroup_mode, pid_t pid, const char *path, bool ensure_missing, xasprintf (&cgroup_path, "/sys/fs/cgroup/%s", path); if (ensure_missing) { - ret = crun_ensure_directory (cgroup_path, 0755, err); + ret = crun_ensure_directory (cgroup_path, 0755, false, err); if (UNLIKELY (ret < 0)) return ret; } diff --git a/src/libcrun/chroot_realpath.c b/src/libcrun/chroot_realpath.c index f34ad296a..06d11dc93 100644 --- a/src/libcrun/chroot_realpath.c +++ b/src/libcrun/chroot_realpath.c @@ -103,7 +103,7 @@ char *chroot_realpath(const char *chroot, const char *path, char resolved_path[] if (path[2] == '\0' || path[2] == '/') { path += 2; /* Ignore ".." at root. */ - if (new_path == got_path_root + 1) + if (new_path == got_path_root || new_path[-1] != '/') continue; /* Handle ".." by backing up. */ while ((--new_path)[-1] != '/'); @@ -145,6 +145,8 @@ char *chroot_realpath(const char *chroot, const char *path, char resolved_path[] return NULL; } } else { + size_t sprintf_len; + /* Note: readlink doesn't add the null byte. */ link_path[n] = '\0'; if (*link_path == '/') @@ -153,14 +155,13 @@ char *chroot_realpath(const char *chroot, const char *path, char resolved_path[] else /* Otherwise back up over this component. */ while (*(--new_path) != '/'); - /* Safe sex check. */ - if (strlen(path) + n >= PATH_MAX - 2) { + + /* Insert symlink contents into path. */ + sprintf_len = snprintf(copy_path, PATH_MAX - 2, "%s%s", link_path, path); + if (sprintf_len >= PATH_MAX - 2) { __set_errno(ENAMETOOLONG); return NULL; } - /* Insert symlink contents into path. */ - strcat(link_path, path); - strcpy(copy_path, link_path); path = copy_path; } #endif /* S_IFLNK */ diff --git a/src/libcrun/container.c b/src/libcrun/container.c index e38d85520..095f40b89 100644 --- a/src/libcrun/container.c +++ b/src/libcrun/container.c @@ -1617,7 +1617,12 @@ libcrun_container_run (libcrun_context_t *context, libcrun_container_t *containe return ret; if (!detach && (options & LIBCRUN_RUN_OPTIONS_PREFORK) == 0) - return libcrun_container_run_internal (container, context, -1, err); + { + ret = libcrun_copy_config_file (context->id, context->state_root, context->bundle, err); + if (UNLIKELY (ret < 0)) + return ret; + return libcrun_container_run_internal (container, context, -1, err); + } ret = pipe (container_ret_status); if (UNLIKELY (ret < 0)) diff --git a/src/libcrun/linux.c b/src/libcrun/linux.c index a9c3b6da3..ca45c7bbf 100644 --- a/src/libcrun/linux.c +++ b/src/libcrun/linux.c @@ -604,10 +604,13 @@ create_dev (libcrun_container_t *container, int devfd, struct device_s *device, const char *fullname = device->path; if (binds) { - cleanup_free char *path_to_container = NULL; - xasprintf (&path_to_container, "%s%s", rootfs, device->path); + char *path_to_container, buffer[PATH_MAX]; - ret = crun_ensure_file (path_to_container, 0700, err); + path_to_container = chroot_realpath (rootfs, device->path, buffer); + if (path_to_container == NULL) + return crun_make_error (err, errno, "cannot resolve '%s'", device->path); + + ret = crun_ensure_file (path_to_container, 0700, true, err); if (UNLIKELY (ret < 0)) return ret; @@ -645,7 +648,7 @@ create_dev (libcrun_container_t *container, int devfd, struct device_s *device, if (tmp != resolved_path) { *tmp = '\0'; - ret = crun_ensure_directory (resolved_path, 0700, err); + ret = crun_ensure_directory (resolved_path, 0700, true, err); if (UNLIKELY (ret < 0)) return ret; *tmp = '/'; @@ -756,7 +759,7 @@ do_masked_and_readonly_paths (libcrun_container_t *container, const char *rootfs if (ret == 0) continue; - dir = crun_dir_p (path, err); + dir = crun_dir_p (path, true, err); if (UNLIKELY (dir < 0)) return ret; @@ -825,6 +828,16 @@ do_pivot (libcrun_container_t *container, const char *rootfs, libcrun_error_t *e if (UNLIKELY (ret < 0)) return crun_make_error (err, errno, "umount oldroot"); + do + { + ret = umount2 (".", MNT_DETACH); + if (ret < 0 && errno == EINVAL) + break; + if (UNLIKELY (ret < 0)) + return crun_make_error (err, errno, "umount oldroot"); + } + while (ret == 0); + ret = chdir ("/"); if (UNLIKELY (ret < 0)) return crun_make_error (err, errno, "chdir to newroot"); @@ -945,7 +958,7 @@ do_mounts (libcrun_container_t *container, const char *rootfs, libcrun_error_t * if (def->mounts[i]->source && (flags & MS_BIND)) { - is_dir = crun_dir_p (def->mounts[i]->source, err); + is_dir = crun_dir_p (def->mounts[i]->source, true, err); if (UNLIKELY (is_dir < 0)) return is_dir; @@ -970,13 +983,13 @@ do_mounts (libcrun_container_t *container, const char *rootfs, libcrun_error_t * if (is_dir) { - ret = crun_ensure_directory (target, 01755, err); + ret = crun_ensure_directory (target, 01755, true, err); if (UNLIKELY (ret < 0)) return ret; } else { - ret = crun_ensure_file (target, 0755, err); + ret = crun_ensure_file (target, 0755, true, err); if (UNLIKELY (ret < 0)) return ret; } @@ -1124,7 +1137,7 @@ do_finalize_notify_socket (libcrun_container_t *container, libcrun_error_t *err) container_notify_socket_path_dir_alloc = xstrdup (container_notify_socket_path); container_notify_socket_path_dir = dirname (container_notify_socket_path_dir_alloc); - ret = crun_ensure_directory (container_notify_socket_path_dir, 0755, err); + ret = crun_ensure_directory (container_notify_socket_path_dir, 0755, false, err); if (UNLIKELY (ret < 0)) return ret; diff --git a/src/libcrun/status.c b/src/libcrun/status.c index 6893591e8..1d0ffd237 100644 --- a/src/libcrun/status.c +++ b/src/libcrun/status.c @@ -47,7 +47,7 @@ get_run_directory (const char *state_root) if (root == NULL) root = xstrdup ("/run/crun"); - ret = crun_ensure_directory (root, 0700, &err); + ret = crun_ensure_directory (root, 0700, false, &err); if (UNLIKELY (ret < 0)) crun_error_release (&err); return root; @@ -160,7 +160,7 @@ libcrun_status_check_directories (const char *state_root, const char *id, libcru cleanup_free char *run_directory = get_run_directory (state_root); int ret; - ret = crun_ensure_directory (run_directory, 0700, err); + ret = crun_ensure_directory (run_directory, 0700, false, err); if (UNLIKELY (ret < 0)) return ret; diff --git a/src/libcrun/utils.c b/src/libcrun/utils.c index 3906531d7..57a8a84fe 100644 --- a/src/libcrun/utils.c +++ b/src/libcrun/utils.c @@ -270,14 +270,26 @@ ensure_directory_internal (char *path, size_t len, int mode, libcrun_error_t *er } int -crun_ensure_directory (const char *path, int mode, libcrun_error_t *err) +crun_ensure_directory (const char *path, int mode, bool nofollow, libcrun_error_t *err) { + int ret; cleanup_free char *tmp = xstrdup (path); - return ensure_directory_internal (tmp, strlen (tmp), mode, err); + ret = ensure_directory_internal (tmp, strlen (tmp), mode, err); + if (UNLIKELY (ret < 0)) + return ret; + + ret = crun_dir_p (path, nofollow, err); + if (UNLIKELY (ret < 0)) + return ret; + + if (ret == 0) + return crun_make_error (err, ENOTDIR, "The path '%s' is not a directory", path); + + return 0; } int -crun_ensure_file (const char *path, int mode, libcrun_error_t *err) +crun_ensure_file (const char *path, int mode, bool nofollow, libcrun_error_t *err) { cleanup_free char *tmp = xstrdup (path); size_t len = strlen (tmp); @@ -289,7 +301,7 @@ crun_ensure_file (const char *path, int mode, libcrun_error_t *err) if (it > tmp) { *it = '\0'; - ret = crun_ensure_directory (tmp, mode, err); + ret = crun_ensure_directory (tmp, mode, nofollow, err); if (UNLIKELY (ret < 0)) return ret; *it = '/'; @@ -326,7 +338,7 @@ get_file_size (int fd, off_t *size) } static int -get_file_type (mode_t *mode, const char *path) +get_file_type (mode_t *mode, bool nofollow, const char *path) { struct stat st; int ret; @@ -334,7 +346,7 @@ get_file_type (mode_t *mode, const char *path) #ifdef HAVE_STATX struct statx stx; - ret = statx (AT_FDCWD, path, AT_STATX_DONT_SYNC, STATX_TYPE, &stx); + ret = statx (AT_FDCWD, path, (nofollow ? AT_SYMLINK_NOFOLLOW : 0) | AT_STATX_DONT_SYNC, STATX_TYPE, &stx); if (UNLIKELY (ret < 0)) { if (errno == ENOSYS) @@ -347,7 +359,10 @@ get_file_type (mode_t *mode, const char *path) fallback: #endif - ret = stat (path, &st); + if (nofollow) + ret = lstat (path, &st); + else + ret = stat (path, &st); if (UNLIKELY (ret < 0)) return ret; *mode = st.st_mode; @@ -355,12 +370,12 @@ get_file_type (mode_t *mode, const char *path) } int -crun_dir_p (const char *path, libcrun_error_t *err) +crun_dir_p (const char *path, bool nofollow, libcrun_error_t *err) { mode_t mode; int ret; - ret = get_file_type (&mode, path); + ret = get_file_type (&mode, nofollow, path); if (UNLIKELY (ret < 0)) return crun_make_error (err, errno, "error stat'ing file '%s'", path); @@ -1202,7 +1217,7 @@ check_access (const char *path) if (ret < 0) return ret; - ret = get_file_type (&mode, path); + ret = get_file_type (&mode, false, path); if (UNLIKELY (ret < 0)) return ret; diff --git a/src/libcrun/utils.h b/src/libcrun/utils.h index 48329c71e..3cd911926 100644 --- a/src/libcrun/utils.h +++ b/src/libcrun/utils.h @@ -69,11 +69,11 @@ int write_file (const char *name, const void *data, size_t len, libcrun_error_t int write_file_at (int dirfd, const char *name, const void *data, size_t len, libcrun_error_t *err); -int crun_ensure_directory (const char *path, int mode, libcrun_error_t *err); +int crun_ensure_directory (const char *path, int mode, bool nofollow, libcrun_error_t *err); -int crun_ensure_file (const char *path, int mode, libcrun_error_t *err); +int crun_ensure_file (const char *path, int mode, bool nofollow, libcrun_error_t *err); -int crun_dir_p (const char *path, libcrun_error_t *err); +int crun_dir_p (const char *path, bool nofollow, libcrun_error_t *err); int detach_process (); diff --git a/tests/tests_libcrun_utils.c b/tests/tests_libcrun_utils.c index f9d4593ce..e4fa00642 100644 --- a/tests/tests_libcrun_utils.c +++ b/tests/tests_libcrun_utils.c @@ -173,11 +173,11 @@ static int test_dir_p () { libcrun_error_t err; - if (crun_dir_p ("/usr", &err) <= 0) + if (crun_dir_p ("/usr", false, &err) <= 0) return -1; - if (crun_dir_p ("/dev/zero", &err) != 0) + if (crun_dir_p ("/dev/zero", false, &err) != 0) return -1; - if (crun_dir_p ("/hopefully/does/not/really/exist", &err) >= 0) + if (crun_dir_p ("/hopefully/does/not/really/exist", false, &err) >= 0) return -1; return 0; }