Skip to content

Commit

Permalink
sysroot: _ostree_sysroot_invisible & _ostree_in_root_mount_namespace
Browse files Browse the repository at this point in the history
  • Loading branch information
ruihe774 committed Dec 19, 2024
1 parent 622444b commit f827879
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 22 deletions.
3 changes: 1 addition & 2 deletions src/libostree/ostree-sysroot-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,7 @@ gboolean _ostree_sysroot_ensure_visible (OstreeSysroot *self, GError **error);
gboolean _ostree_sysroot_ensure_writable (OstreeSysroot *self, GError **error);

gboolean
_ostree_sysroot_enter_mount_namespace (OstreeSysroot *self, GCancellable *cancellable,
GError **error);
_ostree_sysroot_enter_mount_namespace (OstreeSysroot *self, GError **error);

void _ostree_sysroot_emit_journal_msg (OstreeSysroot *self, const char *msg);

Expand Down
58 changes: 38 additions & 20 deletions src/libostree/ostree-sysroot.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,20 +228,22 @@ ostree_sysroot_new_default (void)
}

static gboolean
is_in_root_mount_namespace (GCancellable *cancellable, GError **error)
_ostree_in_root_mount_namespace (gboolean *out_val, GError **error)
{
/* glnx_readlinkat_malloc does not use cancellable acually. */
g_autofree char *mntns_pid1
= glnx_readlinkat_malloc (AT_FDCWD, "/proc/1/ns/mnt", cancellable, error);
= glnx_readlinkat_malloc (AT_FDCWD, "/proc/1/ns/mnt", NULL, error);
if (!mntns_pid1)
return glnx_prefix_error (error, "Reading /proc/1/ns/mnt");
/* mount namespace is per-thread, not per-process */
g_autofree char *cur_thread = g_strdup_printf ("/proc/%d/ns/mnt", gettid ());
g_autofree char *mntns_cur
= glnx_readlinkat_malloc (AT_FDCWD, cur_thread, cancellable, error);
= glnx_readlinkat_malloc (AT_FDCWD, cur_thread, NULL, error);
if (!mntns_cur)
return glnx_prefix_error (error, "Reading %s", cur_thread);

return g_str_equal (mntns_pid1, mntns_cur);
*out_val = g_str_equal (mntns_pid1, mntns_cur);
return TRUE;
}

/**
Expand All @@ -268,15 +270,14 @@ ostree_sysroot_set_mount_namespace_in_use (OstreeSysroot *self)
/* Must be before we're loaded, as otherwise we'd have to close/reopen all our
fds, e.g. the repo */
g_return_if_fail (self->loadstate < OSTREE_SYSROOT_LOAD_STATE_LOADED);
gboolean in_root;
g_autoptr (GError) local_error = NULL;
g_assert (!is_in_root_mount_namespace (NULL, &local_error));
g_assert (local_error == NULL);
g_assert (_ostree_in_root_mount_namespace (&in_root, &local_error) && !in_root);
self->mount_namespace_in_use = TRUE;
}

gboolean
_ostree_sysroot_enter_mount_namespace (OstreeSysroot *self, GCancellable *cancellable,
GError **error)
_ostree_sysroot_enter_mount_namespace (OstreeSysroot *self, GError **error)
{
/* Do nothing if we're not privileged */
if (!ot_util_process_privileged ())
Expand All @@ -287,7 +288,9 @@ _ostree_sysroot_enter_mount_namespace (OstreeSysroot *self, GCancellable *cancel
return TRUE;

// If the mount namespaces are the same, we need to unshare().
if (is_in_root_mount_namespace (cancellable, error))
gboolean in_root;
g_return_val_if_fail (_ostree_in_root_mount_namespace (&in_root, error), FALSE);
if (in_root)
{
if (unshare (CLONE_NEWNS) < 0)
return glnx_throw_errno_prefix (error, "Failed to invoke unshare(CLONE_NEWNS)");
Expand All @@ -296,8 +299,6 @@ _ostree_sysroot_enter_mount_namespace (OstreeSysroot *self, GCancellable *cancel
if (mount (NULL, "/", NULL, MS_PRIVATE | MS_REC | MS_SILENT, NULL) < 0)
return glnx_throw_errno_prefix (error, "Failed to set the mount propagation to private");
}
else
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

ostree_sysroot_set_mount_namespace_in_use (self);

Expand Down Expand Up @@ -334,7 +335,7 @@ ostree_sysroot_initialize_with_mount_namespace (OstreeSysroot *self, GCancellabl
if (!ostree_sysroot_initialize (self, error))
return FALSE;

return _ostree_sysroot_enter_mount_namespace (self, cancellable, error);
return _ostree_sysroot_enter_mount_namespace (self, error);
}

/**
Expand Down Expand Up @@ -400,20 +401,33 @@ remount_writable (const char *path, gboolean *did_remount, GError **error)
}

static gboolean
is_sysroot_invisible (void)
_ostree_sysroot_invisible (gboolean *out_val, GError **error)
{
struct stat stbuf;
gboolean exists;

if (lstat (OTCORE_RUN_OSTREE_PRIVATE "/sysroot-ns", &stbuf) < 0)
if (!ot_path_exists (OTCORE_RUN_OSTREE_PRIVATE "/sysroot-ns", &exists, error))
return FALSE;

if (lstat ("/sysroot/ostree", &stbuf) == 0)
if (!exists)
{
*out_val = FALSE;
return TRUE;
}

if (!ot_path_exists ("/sysroot/ostree", &exists, error))
return FALSE;

if (exists)
{
*out_val = FALSE;
return TRUE;
}

*out_val = TRUE;
return TRUE;
}

/* Unmount covering tmpfs to make /sysroot visible */
/* Make /sysroot visible */
gboolean
_ostree_sysroot_ensure_visible (OstreeSysroot *self, GError **error)
{
Expand All @@ -430,8 +444,10 @@ _ostree_sysroot_ensure_visible (OstreeSysroot *self, GError **error)
if (!self->root_is_ostree_booted)
return TRUE;

gboolean invisible;
g_return_val_if_fail (_ostree_sysroot_invisible (&invisible, error), FALSE);
/* Handle invisible sysroot */
if (is_sysroot_invisible ())
if (invisible)
{
glnx_autofd int sysroot_ns_fd = open (OTCORE_RUN_OSTREE_PRIVATE "/sysroot-ns", O_RDONLY);
if (sysroot_ns_fd < 0)
Expand Down Expand Up @@ -1158,9 +1174,11 @@ ostree_sysroot_initialize (OstreeSysroot *self, GError **error)
return TRUE;
}

if (is_sysroot_invisible ())
gboolean invisible;
g_return_val_if_fail (_ostree_sysroot_invisible (&invisible, error), FALSE);
if (invisible)
{
if (!_ostree_sysroot_enter_mount_namespace (self, NULL, error))
if (!_ostree_sysroot_enter_mount_namespace (self, error))
return FALSE;
if (!_ostree_sysroot_ensure_visible (self, error))
return FALSE;
Expand Down
23 changes: 23 additions & 0 deletions src/libotutil/ot-fs-utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -277,3 +277,26 @@ ot_get_dir_size (int dfd, const char *path, guint64 blocksize, guint64 *out_size

return TRUE;
}

/* Check whether a path exists */
gboolean
ot_path_exists (const char *path, gboolean *out_val, GError **error)
{
g_autoptr (GError) local_error = NULL;

struct stat stbuf;
if (glnx_fstatat (AT_FDCWD, path, &stbuf, 0, &local_error))
{
*out_val = TRUE;
return TRUE;
}

if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
{
*out_val = FALSE;
return TRUE;
}

g_propagate_error (error, local_error);
return FALSE;
}
2 changes: 2 additions & 0 deletions src/libotutil/ot-fs-utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,6 @@ gboolean ot_parse_file_by_line (const char *path, gboolean (*cb) (const char *,
gboolean ot_get_dir_size (int dfd, const char *path, guint64 blocksize, guint64 *out_size,
GCancellable *cancellable, GError **error);

gboolean ot_path_exists (const char *path, gboolean *out_val, GError **error);

G_END_DECLS

0 comments on commit f827879

Please sign in to comment.