mirror of
https://github.com/ostreedev/ostree.git
synced 2024-12-31 21:18:22 +03:00
sysroot: Add an API to initialize with mountns
This lowers down into the C library some logic we have in the binary/app logic, in prep for having more Rust-native CLI code in https://github.com/ostreedev/ostree-rs-ext/pull/412 Basically we want to *ensure* a mount namespace by invoking `unshare()` if necessary, instead of requiring our callers to do this dance. This also helps fix e.g. Closes: https://github.com/ostreedev/ostree/issues/2769
This commit is contained in:
parent
9d652be3b1
commit
599ffefe7f
@ -548,6 +548,7 @@ OstreeSysroot
|
||||
ostree_sysroot_new
|
||||
ostree_sysroot_new_default
|
||||
ostree_sysroot_initialize
|
||||
ostree_sysroot_initialize_with_mount_namespace
|
||||
ostree_sysroot_get_path
|
||||
ostree_sysroot_load
|
||||
ostree_sysroot_load_if_changed
|
||||
|
@ -24,6 +24,7 @@ LIBOSTREE_2022.7 {
|
||||
global:
|
||||
ostree_kernel_args_contains;
|
||||
ostree_kernel_args_delete_if_present;
|
||||
ostree_sysroot_initialize_with_mount_namespace;
|
||||
} LIBOSTREE_2022.5;
|
||||
|
||||
/* Stub section for the stable release *after* this development one; don't
|
||||
|
@ -259,6 +259,63 @@ ostree_sysroot_set_mount_namespace_in_use (OstreeSysroot *self)
|
||||
self->mount_namespace_in_use = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* ostree_sysroot_initialize_with_mount_namespace:
|
||||
*
|
||||
* Prepare the current process for modifying a booted sysroot, if applicable.
|
||||
* This function subsumes the functionality of `ostree_sysroot_initialize`
|
||||
* and may be invoked wherever that function is.
|
||||
*
|
||||
* If the sysroot does not appear to be booted, or where the current process is not uid 0,
|
||||
* this function returns successfully.
|
||||
*
|
||||
* Otherwise, if the process is in the same mount namespace as pid 1, create
|
||||
* a new namespace.
|
||||
*
|
||||
* If you invoke this function, it must be before ostree_sysroot_load(); it may
|
||||
* be invoked before or after ostree_sysroot_initialize().
|
||||
*
|
||||
* Since: 2022.7
|
||||
*/
|
||||
gboolean
|
||||
ostree_sysroot_initialize_with_mount_namespace (OstreeSysroot *self, GCancellable *cancellable, GError **error)
|
||||
{
|
||||
GLNX_AUTO_PREFIX_ERROR ("Initializing with mountns", error);
|
||||
/* Must be before we're loaded, as otherwise we'd have to close/reopen all our
|
||||
fds, e.g. the repo */
|
||||
g_assert (self->loadstate < OSTREE_SYSROOT_LOAD_STATE_LOADED);
|
||||
|
||||
if (!ostree_sysroot_initialize (self, error))
|
||||
return FALSE;
|
||||
|
||||
/* Do nothing if we're not privileged */
|
||||
if (getuid () != 0)
|
||||
return TRUE;
|
||||
|
||||
/* We also assume operating on non-booted roots won't have a readonly sysroot */
|
||||
if (!self->root_is_ostree_booted)
|
||||
return TRUE;
|
||||
|
||||
g_autofree char *mntns_pid1 =
|
||||
glnx_readlinkat_malloc (AT_FDCWD, "/proc/1/ns/mnt", cancellable, error);
|
||||
if (!mntns_pid1)
|
||||
return glnx_prefix_error (error, "Reading /proc/1/ns/mnt");
|
||||
g_autofree char *mntns_self =
|
||||
glnx_readlinkat_malloc (AT_FDCWD, "/proc/self/ns/mnt", cancellable, error);
|
||||
if (!mntns_self)
|
||||
return glnx_prefix_error (error, "Reading /proc/self/ns/mnt");
|
||||
|
||||
// If the mount namespaces are the same, we need to unshare().
|
||||
if (strcmp (mntns_pid1, mntns_self) == 0)
|
||||
{
|
||||
if (unshare (CLONE_NEWNS) < 0)
|
||||
return glnx_throw_errno_prefix (error, "Failed to invoke unshare(CLONE_NEWNS)");
|
||||
}
|
||||
|
||||
ostree_sysroot_set_mount_namespace_in_use (self);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* ostree_sysroot_get_path:
|
||||
* @self: Sysroot
|
||||
|
@ -50,6 +50,9 @@ OstreeSysroot* ostree_sysroot_new_default (void);
|
||||
_OSTREE_PUBLIC
|
||||
void ostree_sysroot_set_mount_namespace_in_use (OstreeSysroot *self);
|
||||
|
||||
_OSTREE_PUBLIC
|
||||
gboolean ostree_sysroot_initialize_with_mount_namespace (OstreeSysroot *self, GCancellable *cancellable, GError **error);
|
||||
|
||||
_OSTREE_PUBLIC
|
||||
GFile *ostree_sysroot_get_path (OstreeSysroot *self);
|
||||
|
||||
|
@ -586,23 +586,9 @@ ostree_admin_sysroot_load (OstreeSysroot *sysroot,
|
||||
{
|
||||
if ((flags & OSTREE_ADMIN_BUILTIN_FLAG_UNLOCKED) == 0)
|
||||
{
|
||||
/* If we're requested to lock the sysroot, first check if we're operating
|
||||
* on a booted (not physical) sysroot. Then find out if the /sysroot
|
||||
* subdir is a read-only mount point, and if so, create a new mount
|
||||
* namespace and tell the sysroot that we've done so. See the docs for
|
||||
* ostree_sysroot_set_mount_namespace_in_use().
|
||||
*
|
||||
* This is a conservative approach; we could just always
|
||||
* unshare() too.
|
||||
*/
|
||||
if (ostree_sysroot_is_booted (sysroot))
|
||||
{
|
||||
gboolean setup_ns = FALSE;
|
||||
if (!maybe_setup_mount_namespace (&setup_ns, error))
|
||||
return FALSE;
|
||||
if (setup_ns)
|
||||
ostree_sysroot_set_mount_namespace_in_use (sysroot);
|
||||
}
|
||||
/* Set up the mount namespace, if applicable */
|
||||
if (!ostree_sysroot_initialize_with_mount_namespace (sysroot, cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
/* Released when sysroot is finalized, or on process exit */
|
||||
if (!ot_admin_sysroot_lock (sysroot, error))
|
||||
|
Loading…
Reference in New Issue
Block a user