~ruther/guix-local

c87a9b855e12fafbafcd2af37fd53374cf965ce8 — Reepca Russelstein 6 months ago d042111
daemon: Restore post-canonicalization permissions after moving.

At this point the value of 'st.st_mode' is from before canonicalization, so
restoring to that will undo the permissions aspect of the canonicalization for
a top-level directory store item.

Fixes #1104, introduced in
ae18b3d9e6 (ae18b3d9e6bd0c184505a094851448d08555e23e).">https://codeberg.org/guix/guix/commit/ae18b3d9e6bd0c184505a094851448d08555e23e).

* nix/libstore/build.cc (DerivationGoal::registerOutputs): update 'st' with
  post-canonicalization permissions before making actualPath
  temporarily-writable.
* tests/store.scm ("build outputs aren't writable"): new test.

Change-Id: I5e5eaa79fa6b7f81e1d12fd285883c762a22ce5a
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
2 files changed, 17 insertions(+), 2 deletions(-)

M nix/libstore/build.cc
M tests/store.scm
M nix/libstore/build.cc => nix/libstore/build.cc +6 -2
@@ 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)

M tests/store.scm => tests/store.scm +11 -0
@@ 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"