mirror of
https://github.com/systemd/systemd.git
synced 2026-08-12 12:16:06 +00:00
repart: when copying files into vfat or similar, do not set ownership
$ mkdir /var/tmp/files $ touch /var/tmp/files/a $ mkdir /var/tmp/conf $ cat >>/var/tmp/conf/esp.conf [Partition] Type=esp Format=vfat CopyFiles=/var/tmp/files:/ $ truncate /var/tmp/disk -s 300M $ sudo systemd-repart --dry-run=no --empty=require --definitions=/var/tmp/conf /var/tmp/disk ... Populating vfat filesystem. Failed to copy '...' to '/run/systemd/mount-root/': Operation not permitted (sd-copy) failed with exit status 1. The issue is that if there's a file owned by non-root and we try to copy it into a newly-created DOS partition, fchown fails: fchown(11</run/systemd/mount-root/...>, 1000, 1000) = -1 EPERM (Operation not permitted) We want to ignore file ownership in such cases, so pass our own UID/GID to copy_tree_at(), which turns the fchown into a noop and let's the operation pass through. Fixes #38863. (cherry picked from commitfe2b35bd58) (cherry picked from commit3a5c0df5c9)
This commit is contained in:
committed by
Luca Boccassi
parent
5e17a74fcf
commit
cea45d7789
@@ -548,6 +548,22 @@ bool fstype_can_fmask_dmask(const char *fstype) {
|
||||
return streq(fstype, "vfat") || (mount_option_supported(fstype, "fmask", "0177") > 0 && mount_option_supported(fstype, "dmask", "0077") > 0);
|
||||
}
|
||||
|
||||
bool fstype_can_ownership(const char *fstype) {
|
||||
/* File systems which are not known to not support uid/gid ownership.
|
||||
* For some types, this can be a bit murky. So just exclude the ones that for sure
|
||||
* don't support with the current implementations in Linux. */
|
||||
|
||||
return !STR_IN_SET(ASSERT_PTR(fstype),
|
||||
"adfs",
|
||||
"exfat",
|
||||
"fat",
|
||||
"hfs",
|
||||
"hpfs",
|
||||
"msdos",
|
||||
"ntfs",
|
||||
"vfat");
|
||||
}
|
||||
|
||||
bool fstype_can_uid_gid(const char *fstype) {
|
||||
/* All file systems that have a uid=/gid= mount option that fixates the owners of all files and
|
||||
* directories, current and future. Note that this does *not* ask the kernel via
|
||||
|
||||
@@ -58,6 +58,7 @@ bool fstype_is_api_vfs(const char *fstype);
|
||||
bool fstype_is_blockdev_backed(const char *fstype);
|
||||
bool fstype_is_ro(const char *fsype);
|
||||
bool fstype_can_discard(const char *fstype);
|
||||
bool fstype_can_ownership(const char *fstype);
|
||||
bool fstype_can_uid_gid(const char *fstype);
|
||||
bool fstype_can_fmask_dmask(const char *fstype);
|
||||
|
||||
|
||||
@@ -6216,6 +6216,8 @@ static int do_copy_files(Context *context, Partition *p, const char *root) {
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
bool copy_ownership = fstype_can_ownership(p->format);
|
||||
|
||||
/* 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
|
||||
@@ -6237,12 +6239,16 @@ static int do_copy_files(Context *context, Partition *p, const char *root) {
|
||||
return log_error_errno(sfd, "Failed to open source file '%s%s': %m", strempty(arg_copy_source), line->source);
|
||||
|
||||
(void) copy_xattr(sfd, NULL, rfd, NULL, COPY_ALL_XATTRS);
|
||||
(void) copy_access(sfd, rfd);
|
||||
if (copy_ownership)
|
||||
(void) copy_access(sfd, rfd);
|
||||
(void) copy_times(sfd, rfd, 0);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
uid_t uid = copy_ownership ? UID_INVALID : getuid();
|
||||
gid_t gid = copy_ownership ? GID_INVALID : getgid();
|
||||
|
||||
FOREACH_ARRAY(line, copy_files, n_copy_files) {
|
||||
_cleanup_hashmap_free_ Hashmap *denylist = NULL;
|
||||
_cleanup_hashmap_free_ Hashmap *subvolumes_by_source_inode = NULL;
|
||||
@@ -6299,14 +6305,14 @@ static int do_copy_files(Context *context, Partition *p, const char *root) {
|
||||
r = copy_tree_at(
|
||||
sfd, ".",
|
||||
pfd, fn,
|
||||
UID_INVALID, GID_INVALID,
|
||||
uid, gid,
|
||||
line->flags,
|
||||
denylist, subvolumes_by_source_inode);
|
||||
} else
|
||||
r = copy_tree_at(
|
||||
sfd, ".",
|
||||
tfd, ".",
|
||||
UID_INVALID, GID_INVALID,
|
||||
uid, gid,
|
||||
line->flags,
|
||||
denylist, subvolumes_by_source_inode);
|
||||
if (r < 0)
|
||||
@@ -6353,7 +6359,8 @@ static int do_copy_files(Context *context, Partition *p, const char *root) {
|
||||
return log_error_errno(r, "Failed to copy '%s' to '%s%s': %m", line->source, strempty(arg_copy_source), line->target);
|
||||
|
||||
(void) copy_xattr(sfd, NULL, tfd, NULL, COPY_ALL_XATTRS);
|
||||
(void) copy_access(sfd, tfd);
|
||||
if (copy_ownership)
|
||||
(void) copy_access(sfd, tfd);
|
||||
(void) copy_times(sfd, tfd, 0);
|
||||
|
||||
if (ts != USEC_INFINITY) {
|
||||
|
||||
Reference in New Issue
Block a user