Backport patch for running inside mock

This commit is contained in:
Colin Walters 2016-08-31 16:48:33 -04:00
parent 526a91c610
commit 59fe1d1510
3 changed files with 152 additions and 36 deletions

View File

@ -0,0 +1,147 @@
From 3ad4e6c72bb5b25745252da4fd1cab6e00827f72 Mon Sep 17 00:00:00 2001
From: Colin Walters <walters@verbum.org>
Date: Mon, 15 Aug 2016 11:58:03 -0400
Subject: [PATCH] bwrap/compose: Add a workaround for Fedora's use of
rpm-ostree-in-mock
Decided to test this on Sunday evening. Of course it was broken =(
(Actually I tested mock-in-Docker but it should be the same)
The core problem is that mock does `chroot()` without using `/`
as a mount point. This breaks an assumption in bwrap that it is.
Now, in theory we could move this same logic down into bwrap to
work around this situation, but for now let's hack it here.
Mock is old, legacy container code that doesn't really do anything
in a modern way - in fact our goal should be to replace it
with a combination of rpm-ostree and bwrap. So carrying this
hack here to get us to that future should be OK for now.
Closes: #431
Approved by: jlebon
---
src/app/rpmostree-compose-builtin-tree.c | 4 ++
src/libpriv/rpmostree-bwrap.c | 81 ++++++++++++++++++++++++++++++++
src/libpriv/rpmostree-bwrap.h | 1 +
3 files changed, 86 insertions(+)
diff --git a/src/app/rpmostree-compose-builtin-tree.c b/src/app/rpmostree-compose-builtin-tree.c
index 5ea1cbe..e49c5e4 100644
--- a/src/app/rpmostree-compose-builtin-tree.c
+++ b/src/app/rpmostree-compose-builtin-tree.c
@@ -630,6 +630,10 @@ rpmostree_compose_builtin_tree (int argc,
"compose tree must presently be run as uid 0 (root)");
goto out;
}
+
+ /* Mock->bwrap bootstrap for Fedora */
+ if (!rpmostree_bwrap_bootstrap_if_in_mock (error))
+ goto out;
/* Test whether or not bwrap is going to work - we will fail inside e.g. a Docker
* container without --privileged or userns exposed.
*/
diff --git a/src/libpriv/rpmostree-bwrap.c b/src/libpriv/rpmostree-bwrap.c
index bd7c793..85e7837 100644
--- a/src/libpriv/rpmostree-bwrap.c
+++ b/src/libpriv/rpmostree-bwrap.c
@@ -108,6 +108,87 @@ rpmostree_run_sync_fchdir_setup (char **argv_array, GSpawnFlags flags,
return TRUE;
}
+/* mock doesn't actually use a mount namespace, and hence bwrap will
+ * fail to remount /. Work around this by doing it here. Fedora
+ * runs rpm-ostree inside of mock instead of Docker or something
+ * more modern.
+ */
+gboolean
+rpmostree_bwrap_bootstrap_if_in_mock (GError **error)
+{
+ const char *env_ps1 = getenv ("PS1");
+ static const char *mock_mounted_paths[] = { "/proc", "/sys" };
+ static const char *findmnt_argv[] = { "findmnt", "/", NULL };
+ g_autofree char *pwd = NULL;
+ int estatus;
+
+ if (!(env_ps1 && strstr (env_ps1, "<mock-chroot>")))
+ return TRUE;
+
+ /* Okay, we detected we're inside mock. Let's double check now
+ * whether or not / is already a mount point. The simplest way to
+ * do this is to execute findmnt...maybe someday we'll link to libmount
+ * but this is legacy.
+ */
+ if (!g_spawn_sync (NULL, (char**)findmnt_argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL,
+ NULL, NULL, &estatus, error))
+ {
+ g_prefix_error (error, "Executing findmnt: ");
+ return FALSE;
+ }
+ /* Did findmnt say / is a mount point? Okay, nothing to do here. */
+ if (estatus == 0)
+ return TRUE;
+
+ pwd = getcwd (NULL, 0);
+
+ g_print ("Detected mock chroot without / as mount, enabling workaround.\n");
+ if (unshare (CLONE_NEWNS) < 0)
+ {
+ glnx_set_prefix_error_from_errno (error, "%s", "unshare(CLONE_NEWNS)");
+ return FALSE;
+ }
+ /* For reasons I don't fully understand, trying to bind mount / -> /
+ * doesn't work. We seem to hit a check in the kernel:
+ *
+ * static int do_change_type(struct path *path, int flag)
+ * {
+ * ...
+ * if (path->dentry != path->mnt->mnt_root)
+ * return -EINVAL;
+ */
+ if (mount ("/", "/mnt", NULL, MS_MGC_VAL | MS_BIND, NULL) != 0)
+ {
+ glnx_set_prefix_error_from_errno (error, "%s", "mount(/ as bind)");
+ return FALSE;
+ }
+ /* Now take the paths that mock mounted (that we need) and move them
+ * underneath the new rootfs mount.
+ */
+ for (guint i = 0; i < G_N_ELEMENTS (mock_mounted_paths); i++)
+ {
+ const char *mockpath = mock_mounted_paths[i];
+ g_autofree char *destpath = g_strconcat ("/mnt", mockpath, NULL);
+ if (mount (mockpath, destpath, NULL, MS_MGC_VAL | MS_MOVE, NULL) != 0)
+ {
+ glnx_set_prefix_error_from_errno (error, "%s", "mount(move)");
+ return FALSE;
+ }
+ }
+ if (chroot ("/mnt") < 0)
+ {
+ glnx_set_error_from_errno (error);
+ return FALSE;
+ }
+ if (chdir (pwd) < 0)
+ {
+ glnx_set_error_from_errno (error);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
/* Execute /bin/true inside a bwrap container on the host */
gboolean
rpmostree_bwrap_selftest (GError **error)
diff --git a/src/libpriv/rpmostree-bwrap.h b/src/libpriv/rpmostree-bwrap.h
index b4bb88c..b464355 100644
--- a/src/libpriv/rpmostree-bwrap.h
+++ b/src/libpriv/rpmostree-bwrap.h
@@ -31,4 +31,5 @@ void rpmostree_ptrarray_append_strdup (GPtrArray *argv_array, ...) G_GNUC_NULL_T
gboolean rpmostree_run_sync_fchdir_setup (char **argv_array, GSpawnFlags flags,
int rootfs_fd, GError **error);
+gboolean rpmostree_bwrap_bootstrap_if_in_mock (GError **error);
gboolean rpmostree_bwrap_selftest (GError **error);
--
2.7.4

View File

@ -1,34 +0,0 @@
From 0fe12fe6a37ee98de5dec70c345d9f0479c47803 Mon Sep 17 00:00:00 2001
From: Jonathan Lebon <jlebon@redhat.com>
Date: Wed, 17 Aug 2016 16:33:51 -0400
Subject: [PATCH] mutate-os-release: skip VERSION_ID
I hit this with librepo subbing out the $releasever with e.g. 7.2016.1
when trying to pull various URLs. It should be enough for the user to
see the ostree version in VERSION and PRETTY_NAME. For applications,
there's OSTREE_VERSION if they need just that.
Closes: #433
Approved by: cgwalters
---
src/libpriv/rpmostree-postprocess.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/libpriv/rpmostree-postprocess.c b/src/libpriv/rpmostree-postprocess.c
index 17ec151..d0566bd 100644
--- a/src/libpriv/rpmostree-postprocess.c
+++ b/src/libpriv/rpmostree-postprocess.c
@@ -1380,8 +1380,9 @@ mutate_os_release (const char *contents,
if (strlen (line) == 0)
continue;
+ /* NB: we don't mutate VERSION_ID because some libraries expect well-known
+ * values there*/
if (g_str_has_prefix (line, "VERSION=") || \
- g_str_has_prefix (line, "VERSION_ID=") || \
g_str_has_prefix (line, "PRETTY_NAME="))
{
g_autofree char *new_line = NULL;
--
2.7.4

View File

@ -1,11 +1,11 @@
Summary: Client side upgrade program and server side compose tool
Name: rpm-ostree
Version: 2016.7
Release: 2%{?dist}
Release: 3%{?dist}
#VCS: https://github.com/cgwalters/rpm-ostree
# This tarball is generated via "make -f Makefile.dist-packaging dist-snapshot"
Source0: rpm-ostree-%{version}.tar.xz
Patch0: 0001-mutate-os-release-skip-VERSION_ID.patch
Patch0: 0001-bwrap-compose-Add-a-workaround-for-Fedora-s-use-of-r.patch
License: LGPLv2+
URL: https://github.com/projectatomic/rpm-ostree
# We always run autogen.sh
@ -122,6 +122,9 @@ python autofiles.py > files.devel \
%files devel -f files.devel
%changelog
* Wed Aug 31 2016 Colin Walters <walters@verbum.org> - 2016.7-3
- Backport patch for running inside mock
* Sat Aug 13 2016 walters@redhat.com - 2016.6-3
- New upstream version