summaryrefslogtreecommitdiff
path: root/src/libostree
diff options
context:
space:
mode:
authorColin Walters <walters@verbum.org>2022-11-21 15:16:04 -0500
committerColin Walters <walters@verbum.org>2022-11-22 08:45:13 -0500
commit599ffefe7f069712d54f63f67e4a6f92570c554e (patch)
tree7d3a79a87ede87708d79172502a26e5c8db0061f /src/libostree
parent9d652be3b18d5899d3aa36868551dc5af5ceef2e (diff)
downloadostree-599ffefe7f069712d54f63f67e4a6f92570c554e.tar.gz
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
Diffstat (limited to 'src/libostree')
-rw-r--r--src/libostree/libostree-devel.sym1
-rw-r--r--src/libostree/ostree-sysroot.c57
-rw-r--r--src/libostree/ostree-sysroot.h3
3 files changed, 61 insertions, 0 deletions
diff --git a/src/libostree/libostree-devel.sym b/src/libostree/libostree-devel.sym
index 6a82433a..8f374bbe 100644
--- a/src/libostree/libostree-devel.sym
+++ b/src/libostree/libostree-devel.sym
@@ -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
diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c
index b15265f5..4c63a657 100644
--- a/src/libostree/ostree-sysroot.c
+++ b/src/libostree/ostree-sysroot.c
@@ -260,6 +260,63 @@ ostree_sysroot_set_mount_namespace_in_use (OstreeSysroot *self)
}
/**
+ * 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
*
diff --git a/src/libostree/ostree-sysroot.h b/src/libostree/ostree-sysroot.h
index 0cde9e44..23c7139a 100644
--- a/src/libostree/ostree-sysroot.h
+++ b/src/libostree/ostree-sysroot.h
@@ -51,6 +51,9 @@ _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);
_OSTREE_PUBLIC