sysroot: Ensure deployment detection works when using composefs
authorAlexander Larsson <alexl@redhat.com>
Tue, 16 May 2023 08:17:32 +0000 (10:17 +0200)
committerAlexander Larsson <alexl@redhat.com>
Wed, 31 May 2023 08:57:37 +0000 (10:57 +0200)
In the case of composefs, we cannot compare the devino of the rootfs
and the deploy dir, because the root is the composefs mount, not a
bind mount. Instead we check the devino of the etc subdir of the
deploy, because this is a bind mount even when using composefs.

src/libostree/ostree-sysroot-private.h
src/libostree/ostree-sysroot.c

index 6c1c5d3e9cca647581f2198ae175f147b66010b6..78e736fca8fcbcfbcf8aaad67a9ec133bd5809a1 100644 (file)
@@ -70,9 +70,11 @@ struct OstreeSysroot
   OstreeSysrootLoadState loadstate;
   gboolean mount_namespace_in_use; /* TRUE if caller has told us they used CLONE_NEWNS */
   gboolean root_is_ostree_booted;  /* TRUE if sysroot is / and we are booted via ostree */
-  /* The device/inode for /, used to detect booted deployment */
+  /* The device/inode for / and /etc, used to detect booted deployment */
   dev_t root_device;
   ino_t root_inode;
+  dev_t etc_device;
+  ino_t etc_inode;
 
   gboolean is_physical; /* TRUE if we're pointed at physical storage root and not a deployment */
   GPtrArray *deployments;
index ca8b32771737293391f3a55ba1dba8546e67d925..946bd35359b7f6a73c2fccfc8e423171c9909418 100644 (file)
@@ -799,14 +799,26 @@ parse_deployment (OstreeSysroot *self, const char *boot_link, OstreeDeployment *
   if (looking_for_booted_deployment)
     {
       struct stat stbuf;
+      struct stat etc_stbuf = {};
       if (!glnx_fstat (deployment_dfd, &stbuf, error))
         return FALSE;
+
+      /* We look for either the root or the etc subdir of the
+       * deployment. We need to do this, because when using composefs,
+       * the root is not a bind mount of the deploy dir, but the etc
+       * dir is.
+       */
+
+      if (!glnx_fstatat_allow_noent (deployment_dfd, "etc", &etc_stbuf, 0, error))
+        return FALSE;
+
       /* A bit ugly, we're assigning to a sysroot-owned variable from deep in
        * this parsing code. But eh, if something fails the sysroot state can't
        * be relied on anyways.
        */
       is_booted_deployment
-          = (stbuf.st_dev == self->root_device && stbuf.st_ino == self->root_inode);
+          = (stbuf.st_dev == self->root_device && stbuf.st_ino == self->root_inode)
+            || (etc_stbuf.st_dev == self->etc_device && etc_stbuf.st_ino == self->etc_inode);
     }
 
   g_autoptr (OstreeDeployment) ret_deployment
@@ -1003,6 +1015,17 @@ ostree_sysroot_initialize (OstreeSysroot *self, GError **error)
         self->root_inode = root_stbuf.st_ino;
       }
 
+      {
+        struct stat etc_stbuf;
+        if (!glnx_fstatat_allow_noent (AT_FDCWD, "/etc", &etc_stbuf, 0, error))
+          return FALSE;
+        if (errno != ENOENT)
+          {
+            self->etc_device = etc_stbuf.st_dev;
+            self->etc_inode = etc_stbuf.st_ino;
+          }
+      }
+
       struct stat self_stbuf;
       if (!glnx_fstatat (AT_FDCWD, gs_file_get_path_cached (self->path), &self_stbuf, 0, error))
         return FALSE;