Subject: Re: bug#78355: guix-ownership inconsistent state

From: Ludovic Courtès <[email-masked]>
Date: Tue, 10 Jun 2025 15:48:46 +0200

Hi Rutherther,

Rutherther <[email-masked]> writes:

> The guix-ownership service checks /gnu/store ownership to check if the
> whole store and all files important for the daemon (/etc/guix,
> /var/guix) are owned by the appropriate user.
>
> If the folder isn't owned by appropriate user, it moves to those steps:
> 1. Fix permissions in /gnu/store - first under it, then /gnu/store
> itself as last step
> 2. Fix /var/guix
> 3. Fix /etc/guix
> 4. Fix /var/log/guix
>
> So from those laid out steps it should be obvious that if guix-ownership
> service somehow stops between steps 1 and 2, it will never recover
> ownerships of /var/guix, /etc/guix and /var/log/guix. /gnu/store should
> change owner as last.

Sorry for dropping the ball.  How about the patch below?

Note that it would only help if the user retries to change ownership in
the same direction after interrupting the service; ownership change
remains fundamentally non-atomic so it’s still possible to end up in a
partially chown’d state, if one insists.

Thanks,
Ludo’.

diff --git a/gnu/services/base.scm b/gnu/services/base.scm
index edc6f45850..c2851ef1a9 100644
--- a/gnu/services/base.scm
+++ b/gnu/services/base.scm
@@ -1997,10 +1997,9 @@ (define (guix-ownership-change-program)
                              lstat))
 
          (define (claim-data-ownership uid gid)
-           (format #t "Changing file ownership for /gnu/store \
+           (format #t "Changing file ownership for ~a \
 and data directories to ~a:~a...~%"
-                   uid gid)
-           (change-ownership #$(%store-prefix) uid gid)
+                   #$(%store-prefix) uid gid)
            (let ((excluded '("." ".." "profiles" "userpool")))
              (for-each (lambda (directory)
                          (change-ownership (in-vicinity "/var/guix" directory)
@@ -2012,7 +2011,11 @@ (define (guix-ownership-change-program)
            (chown "/var/guix" uid gid)
            (change-ownership "/etc/guix" uid gid)
            (mkdir-p "/var/log/guix")
-           (change-ownership "/var/log/guix" uid gid))
+           (change-ownership "/var/log/guix" uid gid)
+
+           ;; Change the store last so that, if this service is interrupted,
+           ;; ownership appears as having yet to be changed.
+           (change-ownership #$(%store-prefix) uid gid))
 
          (match (command-line)
            ((_ (= string->number (? integer? uid))