dissect: do not follow copy-to directory symlinks

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>
This commit is contained in:
dongshengyuan
2026-07-09 11:01:29 +02:00
committed by Lennart Poettering
parent 04915e3d37
commit 4839cb914e
+5 -1
View File
@@ -1490,8 +1490,12 @@ static int action_list_or_mtree_or_copy_or_make_archive(DissectedImage *m, LoopD
/* 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);