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.
This commit is contained in:
Alexander Larsson 2023-05-16 10:17:32 +02:00
parent 11d7587e40
commit d47a90347b
2 changed files with 27 additions and 2 deletions

View File

@ -70,9 +70,11 @@ struct OstreeSysroot
OstreeSysrootLoadState loadstate; OstreeSysrootLoadState loadstate;
gboolean mount_namespace_in_use; /* TRUE if caller has told us they used CLONE_NEWNS */ 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 */ 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; dev_t root_device;
ino_t root_inode; 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 */ gboolean is_physical; /* TRUE if we're pointed at physical storage root and not a deployment */
GPtrArray *deployments; GPtrArray *deployments;

View File

@ -799,14 +799,26 @@ parse_deployment (OstreeSysroot *self, const char *boot_link, OstreeDeployment *
if (looking_for_booted_deployment) if (looking_for_booted_deployment)
{ {
struct stat stbuf; struct stat stbuf;
struct stat etc_stbuf = {};
if (!glnx_fstat (deployment_dfd, &stbuf, error)) if (!glnx_fstat (deployment_dfd, &stbuf, error))
return FALSE; 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 /* 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 * this parsing code. But eh, if something fails the sysroot state can't
* be relied on anyways. * be relied on anyways.
*/ */
is_booted_deployment 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 g_autoptr (OstreeDeployment) ret_deployment
@ -1003,6 +1015,17 @@ ostree_sysroot_initialize (OstreeSysroot *self, GError **error)
self->root_inode = root_stbuf.st_ino; 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; struct stat self_stbuf;
if (!glnx_fstatat (AT_FDCWD, gs_file_get_path_cached (self->path), &self_stbuf, 0, error)) if (!glnx_fstatat (AT_FDCWD, gs_file_get_path_cached (self->path), &self_stbuf, 0, error))
return FALSE; return FALSE;