diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 0a4de96d51d..a48214a9c0a 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -3139,10 +3139,14 @@ void DerivationGoal::registerOutputs() replaceValidPath(path, actualPath); else if (buildMode != bmCheck) { - if (S_ISDIR(st.st_mode)) + if (S_ISDIR(st.st_mode)) { + if (lstat(actualPath.c_str(), &st) == -1) + throw SysError(format("getting canonicalized permissions of directory `%1%'") % actualPath); /* Change mode on the directory to allow for rename(2). */ - chmod(actualPath.c_str(), st.st_mode | 0700); + if (chmod(actualPath.c_str(), st.st_mode | 0700) == -1) + throw SysError(format("making `%1%' writable for move from chroot to store") % actualPath); + } if (rename(actualPath.c_str(), path.c_str()) == -1) throw SysError(format("moving build output `%1%' from the chroot to the store") % path); if (S_ISDIR(st.st_mode) && chmod(path.c_str(), st.st_mode) == -1) diff --git a/tests/store.scm b/tests/store.scm index 112ea7e2fcb..16dcbf2396d 100644 --- a/tests/store.scm +++ b/tests/store.scm @@ -417,6 +417,17 @@ get-string-all) a)))) +;; https://codeberg.org/guix/guix/issues/1104 +(test-equal "build outputs aren't writable" + #o555 + (let ((drv (build-expression->derivation %store "writable-output" + `(begin + ,(random-text) + (mkdir %output) + (chmod %output #o755))))) + (build-derivations %store (list drv)) + (stat:perms (stat (derivation->output-path drv "out"))))) + (unless (unprivileged-user-namespace-supported?) (test-skip 1)) (test-equal "isolated environment"