mirror of
https://github.com/ostreedev/ostree.git
synced 2025-01-03 05:18:24 +03:00
sysroot: _ostree_sysroot_invisible & _ostree_in_root_mount_namespace
This commit is contained in:
parent
3dc167e2ee
commit
300d21c1cb
@ -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_ensure_writable (OstreeSysroot *self, GError **error);
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
_ostree_sysroot_enter_mount_namespace (OstreeSysroot *self, GCancellable *cancellable,
|
_ostree_sysroot_enter_mount_namespace (OstreeSysroot *self, GError **error);
|
||||||
GError **error);
|
|
||||||
|
|
||||||
void _ostree_sysroot_emit_journal_msg (OstreeSysroot *self, const char *msg);
|
void _ostree_sysroot_emit_journal_msg (OstreeSysroot *self, const char *msg);
|
||||||
|
|
||||||
|
@ -228,20 +228,22 @@ ostree_sysroot_new_default (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
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
|
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)
|
if (!mntns_pid1)
|
||||||
return glnx_prefix_error (error, "Reading /proc/1/ns/mnt");
|
return glnx_prefix_error (error, "Reading /proc/1/ns/mnt");
|
||||||
/* mount namespace is per-thread, not per-process */
|
/* mount namespace is per-thread, not per-process */
|
||||||
g_autofree char *cur_thread = g_strdup_printf ("/proc/%d/ns/mnt", gettid ());
|
g_autofree char *cur_thread = g_strdup_printf ("/proc/%d/ns/mnt", gettid ());
|
||||||
g_autofree char *mntns_cur
|
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)
|
if (!mntns_cur)
|
||||||
return glnx_prefix_error (error, "Reading %s", cur_thread);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -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
|
/* Must be before we're loaded, as otherwise we'd have to close/reopen all our
|
||||||
fds, e.g. the repo */
|
fds, e.g. the repo */
|
||||||
g_return_if_fail (self->loadstate < OSTREE_SYSROOT_LOAD_STATE_LOADED);
|
g_return_if_fail (self->loadstate < OSTREE_SYSROOT_LOAD_STATE_LOADED);
|
||||||
|
gboolean in_root;
|
||||||
g_autoptr (GError) local_error = NULL;
|
g_autoptr (GError) local_error = NULL;
|
||||||
g_assert (!is_in_root_mount_namespace (NULL, &local_error));
|
g_assert (_ostree_in_root_mount_namespace (&in_root, &local_error) && !in_root);
|
||||||
g_assert (local_error == NULL);
|
|
||||||
self->mount_namespace_in_use = TRUE;
|
self->mount_namespace_in_use = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
_ostree_sysroot_enter_mount_namespace (OstreeSysroot *self, GCancellable *cancellable,
|
_ostree_sysroot_enter_mount_namespace (OstreeSysroot *self, GError **error)
|
||||||
GError **error)
|
|
||||||
{
|
{
|
||||||
/* Do nothing if we're not privileged */
|
/* Do nothing if we're not privileged */
|
||||||
if (!ot_util_process_privileged ())
|
if (!ot_util_process_privileged ())
|
||||||
@ -287,7 +288,9 @@ _ostree_sysroot_enter_mount_namespace (OstreeSysroot *self, GCancellable *cancel
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
// If the mount namespaces are the same, we need to unshare().
|
// 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)
|
if (unshare (CLONE_NEWNS) < 0)
|
||||||
return glnx_throw_errno_prefix (error, "Failed to invoke unshare(CLONE_NEWNS)");
|
return glnx_throw_errno_prefix (error, "Failed to invoke unshare(CLONE_NEWNS)");
|
||||||
@ -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)
|
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");
|
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);
|
ostree_sysroot_set_mount_namespace_in_use (self);
|
||||||
|
|
||||||
@ -334,7 +335,7 @@ ostree_sysroot_initialize_with_mount_namespace (OstreeSysroot *self, GCancellabl
|
|||||||
if (!ostree_sysroot_initialize (self, error))
|
if (!ostree_sysroot_initialize (self, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
return _ostree_sysroot_enter_mount_namespace (self, cancellable, error);
|
return _ostree_sysroot_enter_mount_namespace (self, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -400,20 +401,33 @@ remount_writable (const char *path, gboolean *did_remount, GError **error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
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;
|
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;
|
return FALSE;
|
||||||
|
|
||||||
|
if (exists)
|
||||||
|
{
|
||||||
|
*out_val = FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_val = TRUE;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unmount covering tmpfs to make /sysroot visible */
|
/* Make /sysroot visible */
|
||||||
gboolean
|
gboolean
|
||||||
_ostree_sysroot_ensure_visible (OstreeSysroot *self, GError **error)
|
_ostree_sysroot_ensure_visible (OstreeSysroot *self, GError **error)
|
||||||
{
|
{
|
||||||
@ -430,8 +444,10 @@ _ostree_sysroot_ensure_visible (OstreeSysroot *self, GError **error)
|
|||||||
if (!self->root_is_ostree_booted)
|
if (!self->root_is_ostree_booted)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
gboolean invisible;
|
||||||
|
g_return_val_if_fail (_ostree_sysroot_invisible (&invisible, error), FALSE);
|
||||||
/* Handle invisible sysroot */
|
/* Handle invisible sysroot */
|
||||||
if (is_sysroot_invisible ())
|
if (invisible)
|
||||||
{
|
{
|
||||||
glnx_autofd int sysroot_ns_fd = open (OTCORE_RUN_OSTREE_PRIVATE "/sysroot-ns", O_RDONLY);
|
glnx_autofd int sysroot_ns_fd = open (OTCORE_RUN_OSTREE_PRIVATE "/sysroot-ns", O_RDONLY);
|
||||||
if (sysroot_ns_fd < 0)
|
if (sysroot_ns_fd < 0)
|
||||||
@ -1158,9 +1174,11 @@ ostree_sysroot_initialize (OstreeSysroot *self, GError **error)
|
|||||||
return TRUE;
|
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;
|
return FALSE;
|
||||||
if (!_ostree_sysroot_ensure_visible (self, error))
|
if (!_ostree_sysroot_ensure_visible (self, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -277,3 +277,26 @@ ot_get_dir_size (int dfd, const char *path, guint64 blocksize, guint64 *out_size
|
|||||||
|
|
||||||
return TRUE;
|
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;
|
||||||
|
}
|
||||||
|
@ -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,
|
gboolean ot_get_dir_size (int dfd, const char *path, guint64 blocksize, guint64 *out_size,
|
||||||
GCancellable *cancellable, GError **error);
|
GCancellable *cancellable, GError **error);
|
||||||
|
|
||||||
|
gboolean ot_path_exists (const char *path, gboolean *out_val, GError **error);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
Loading…
Reference in New Issue
Block a user