postprocess: Switch to using bwrap for script execution

The previous commit https://github.com/projectatomic/rpm-ostree/pull/422
introduced a regression in the "outside of a container" path - we
get `EINVAL` trying to `mount("proc",...)` and honestly I'm not sure why.

We can either back up or plow forward, and it turns out to be
pretty straightforward to complete the port to using bwrap.

I extracted the bwrap-execution code out of the RPM script engine,
because the treecompose model is currently different (no hardlinks
yet).

NOTE: A *very* important side effect of this is that we now
require "privileged" containers on hosts without user namespaces,
and on userns hosts, require `CLONE_NEWUSER` to be exported to the
container host.

In general though, the previous path of blindly executing scripts as root
without e.g. `proc` mounted was just bad.

Closes: #429
Approved by: jlebon
This commit is contained in:
Colin Walters 2016-08-12 16:17:35 -04:00 committed by Atomic Bot
parent 88a130da09
commit 551e4c91f9

View File

@ -27,6 +27,7 @@
#include <json-glib/json-glib.h> #include <json-glib/json-glib.h>
#include <stdio.h> #include <stdio.h>
#include <utime.h> #include <utime.h>
#include <err.h>
#include <sys/types.h> #include <sys/types.h>
#include <pwd.h> #include <pwd.h>
#include <grp.h> #include <grp.h>
@ -37,6 +38,7 @@
#include <gio/gunixoutputstream.h> #include <gio/gunixoutputstream.h>
#include "rpmostree-postprocess.h" #include "rpmostree-postprocess.h"
#include "rpmostree-bwrap.h"
#include "rpmostree-passwd-util.h" #include "rpmostree-passwd-util.h"
#include "rpmostree-rpm-util.h" #include "rpmostree-rpm-util.h"
#include "rpmostree-json-parsing.h" #include "rpmostree-json-parsing.h"
@ -66,21 +68,43 @@ run_sync_in_root_at (int rootfs_fd,
char **child_argv, char **child_argv,
GError **error) GError **error)
{ {
gboolean ret = FALSE; const GSpawnFlags bwrap_spawnflags = G_SPAWN_SEARCH_PATH;
pid_t child = glnx_libcontainer_run_chroot_at_private (rootfs_fd, binpath, child_argv); g_autoptr(GPtrArray) bwrap_argv = NULL;
if (child == -1) bwrap_argv = rpmostree_bwrap_base_argv_new_for_rootfs (rootfs_fd, error);
if (!bwrap_argv)
return FALSE;
/* Bind all of the primary toplevel dirs; unlike the script case, treecompose
* isn't yet operating on hardlinks, so we can just bind mount things mutably.
*/
rpmostree_ptrarray_append_strdup (bwrap_argv,
"--bind", "usr", "/usr",
"--bind", "var", "/var",
"--bind", "etc", "/etc",
NULL);
g_ptr_array_add (bwrap_argv, g_strdup (binpath));
/* https://github.com/projectatomic/bubblewrap/issues/91 */
{ gboolean first = TRUE;
for (char **iter = child_argv; iter && *iter; iter++)
{ {
_rpmostree_set_error_from_errno (error, errno); if (first)
goto out; first = FALSE;
else
g_ptr_array_add (bwrap_argv, g_strdup (*iter));
}
}
g_ptr_array_add (bwrap_argv, NULL);
if (!rpmostree_run_sync_fchdir_setup ((char**)bwrap_argv->pdata, bwrap_spawnflags,
rootfs_fd, error))
{
g_prefix_error (error, "Executing bwrap: ");
return FALSE;
} }
if (!_rpmostree_sync_wait_on_pid (child, error)) return TRUE;
goto out;
ret = TRUE;
out:
return ret;
} }
static gboolean static gboolean