diff --git a/src/partition/repart.c b/src/partition/repart.c index 93dfb5fb3e8..20f571e4cb0 100644 --- a/src/partition/repart.c +++ b/src/partition/repart.c @@ -3752,6 +3752,31 @@ static int do_copy_files(Partition *p, const char *root, const Set *denylist) { assert(p); assert(root); + /* copy_tree_at() automatically copies the permissions of source directories to target directories if + * it created them. However, the root directory is created by us, so we have to manually take care + * that it is initialized. We use the first source directory targeting "/" as the metadata source for + * the root directory. */ + STRV_FOREACH_PAIR(source, target, p->copy_files) { + _cleanup_close_ int rfd = -EBADF, sfd = -EBADF; + + if (!path_equal(*target, "/")) + continue; + + rfd = open(root, O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW); + if (rfd < 0) + return rfd; + + sfd = chase_symlinks_and_open(*source, arg_root, CHASE_PREFIX_ROOT, O_PATH|O_DIRECTORY|O_CLOEXEC|O_NOCTTY, NULL); + if (sfd < 0) + return log_error_errno(sfd, "Failed to open source file '%s%s': %m", strempty(arg_root), *source); + + (void) copy_xattr(sfd, NULL, rfd, NULL, COPY_ALL_XATTRS); + (void) copy_access(sfd, rfd); + (void) copy_times(sfd, rfd, 0); + + break; + } + STRV_FOREACH_PAIR(source, target, p->copy_files) { _cleanup_close_ int sfd = -EBADF, pfd = -EBADF, tfd = -EBADF;