diff options
author | alois31 <alois1@gmx-topmail.de> | 2024-09-21 07:55:13 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@localhost> | 2024-09-21 07:55:13 +0000 |
commit | 5f298f74c92402a8390b01c736463b17b36277e3 (patch) | |
tree | d839f031bb730f2befc01ada8c40ec23db09cebc /src/libstore | |
parent | 79246a37337c5df2224dbc2461c722e1e678f6de (diff) | |
parent | 3f07c65510d5f907c75803e7d58884bdafb78132 (diff) |
Merge "local-store: make extended attribute handling more robust" into main
Diffstat (limited to 'src/libstore')
-rw-r--r-- | src/libstore/local-store.cc | 30 |
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); |