When copying a directory into an image, open an existing destination
with O_NOFOLLOW before passing it to copy_tree_at(). This rejects a
symlink used as the final destination component without a separate
stat-before-use check.
Previously the pre-opened destination followed that symlink. That
allowed --copy-to to be redirected outside the image root when the
image was a directory tree.
If the destination does not exist yet, keep delegating creation to
copy_tree_at(). Real existing directories still use COPY_MERGE through
the opened directory fd.
Signed-off-by: dongshengyuan <dongshengyuan@uniontech.com>
/* We are looking at a directory. */
- target_fd = openat(dfd, bn, O_RDONLY|O_DIRECTORY|O_CLOEXEC);
+ target_fd = openat(dfd, bn, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
if (target_fd < 0) {
+ if (errno == ELOOP)
+ return log_error_errno(SYNTHETIC_ERRNO(ELOOP),
+ "Refusing to copy directory to symlink destination '%s'.", arg_target);
+
if (errno != ENOENT)
return log_error_errno(errno, "Failed to open destination '%s': %m", arg_target);