From 7aaf24c03d26eb65094603b58a3b3cfb7e854616 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Thu, 27 Apr 2023 12:46:09 +0200 Subject: [PATCH] sysroot: Ensure deployment detection works when using composefs 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 | 4 +++- src/libostree/ostree-sysroot.c | 26 ++++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/libostree/ostree-sysroot-private.h b/src/libostree/ostree-sysroot-private.h index 57ac6824ca..6baccfe6cc 100644 --- a/src/libostree/ostree-sysroot-private.h +++ b/src/libostree/ostree-sysroot-private.h @@ -64,9 +64,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; diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c index b8edcd64a9..e10a1a90ce 100644 --- a/src/libostree/ostree-sysroot.c +++ b/src/libostree/ostree-sysroot.c @@ -837,14 +837,26 @@ parse_deployment (OstreeSysroot *self, 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); + is_booted_deployment = + (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 @@ -1049,6 +1061,16 @@ ostree_sysroot_initialize (OstreeSysroot *self, 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;