Skip to content

Commit

Permalink
sysroot: Ensure deployment detection works when using composefs
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
alexlarsson committed Apr 28, 2023
1 parent c70ef9b commit 7aaf24c
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 3 deletions.
4 changes: 3 additions & 1 deletion src/libostree/ostree-sysroot-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
26 changes: 24 additions & 2 deletions src/libostree/ostree-sysroot.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 7aaf24c

Please sign in to comment.