aboutsummaryrefslogtreecommitdiff
path: root/src/libstore
diff options
context:
space:
mode:
authoralois31 <alois1@gmx-topmail.de>2024-09-21 07:55:13 +0000
committerGerrit Code Review <gerrit@localhost>2024-09-21 07:55:13 +0000
commit5f298f74c92402a8390b01c736463b17b36277e3 (patch)
treed839f031bb730f2befc01ada8c40ec23db09cebc /src/libstore
parent79246a37337c5df2224dbc2461c722e1e678f6de (diff)
parent3f07c65510d5f907c75803e7d58884bdafb78132 (diff)
Merge "local-store: make extended attribute handling more robust" into main
Diffstat (limited to 'src/libstore')
-rw-r--r--src/libstore/local-store.cc30
1 files changed, 16 insertions, 14 deletions
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc
index 8f92255f5..1af0f54de 100644
--- a/src/libstore/local-store.cc
+++ b/src/libstore/local-store.cc
@@ -664,6 +664,20 @@ static void canonicalisePathMetaData_(
if (!(S_ISREG(st.st_mode) || S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode)))
throw Error("file '%1%' has an unsupported type", path);
+ /* Fail if the file is not owned by the build user. This prevents
+ us from messing up the ownership/permissions of files
+ hard-linked into the output (e.g. "ln /etc/shadow $out/foo").
+ However, ignore files that we chown'ed ourselves previously to
+ ensure that we don't fail on hard links within the same build
+ (i.e. "touch $out/foo; ln $out/foo $out/bar"). */
+ if (uidRange && (st.st_uid < uidRange->first || st.st_uid > uidRange->second)) {
+ if (S_ISDIR(st.st_mode) || !inodesSeen.count(Inode(st.st_dev, st.st_ino)))
+ throw BuildError("invalid ownership on file '%1%'", path);
+ mode_t mode = st.st_mode & ~S_IFMT;
+ assert(S_ISLNK(st.st_mode) || (st.st_uid == geteuid() && (mode == 0444 || mode == 0555) && st.st_mtime == mtimeStore));
+ return;
+ }
+
#if __linux__
/* Remove extended attributes / ACLs. */
ssize_t eaSize = llistxattr(path.c_str(), nullptr, 0);
@@ -677,6 +691,8 @@ static void canonicalisePathMetaData_(
if ((eaSize = llistxattr(path.c_str(), eaBuf.data(), eaBuf.size())) < 0)
throw SysError("querying extended attributes of '%s'", path);
+ if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))
+ chmod(path.c_str(), st.st_mode | S_IWUSR);
for (auto & eaName: tokenizeString<Strings>(std::string(eaBuf.data(), eaSize), std::string("\000", 1))) {
if (settings.ignoredAcls.get().count(eaName)) continue;
if (lremovexattr(path.c_str(), eaName.c_str()) == -1)
@@ -685,20 +701,6 @@ static void canonicalisePathMetaData_(
}
#endif
- /* Fail if the file is not owned by the build user. This prevents
- us from messing up the ownership/permissions of files
- hard-linked into the output (e.g. "ln /etc/shadow $out/foo").
- However, ignore files that we chown'ed ourselves previously to
- ensure that we don't fail on hard links within the same build
- (i.e. "touch $out/foo; ln $out/foo $out/bar"). */
- if (uidRange && (st.st_uid < uidRange->first || st.st_uid > uidRange->second)) {
- if (S_ISDIR(st.st_mode) || !inodesSeen.count(Inode(st.st_dev, st.st_ino)))
- throw BuildError("invalid ownership on file '%1%'", path);
- mode_t mode = st.st_mode & ~S_IFMT;
- assert(S_ISLNK(st.st_mode) || (st.st_uid == geteuid() && (mode == 0444 || mode == 0555) && st.st_mtime == mtimeStore));
- return;
- }
-
inodesSeen.insert(Inode(st.st_dev, st.st_ino));
canonicaliseTimestampAndPermissions(path, st);