guix_mirror_bot pushed a commit to branch master
in repository guix.

commit c87a9b855e12fafbafcd2af37fd53374cf965ce8
Author: Reepca Russelstein <[email protected]>
AuthorDate: Fri Sep 5 01:59:12 2025 -0500

    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 
(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 <[email protected]>
---
 nix/libstore/build.cc |  8 ++++++--
 tests/store.scm       | 11 +++++++++++
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc
index 0a4de96d51..a48214a9c0 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 112ea7e2fc..16dcbf2396 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"

Reply via email to