lib: Extract bwrap-executing internal API
The treecompose code will learn how to use bwrap instead of libcontainer in libglnx, since the latter is a buggy copy of a subset of the former. Closes: #429 Approved by: jlebon
This commit is contained in:
parent
873f4766d7
commit
88a130da09
@ -30,6 +30,8 @@ librpmostreepriv_la_SOURCES = \
|
||||
src/libpriv/rpmostree-refts.c \
|
||||
src/libpriv/rpmostree-core.c \
|
||||
src/libpriv/rpmostree-core.h \
|
||||
src/libpriv/rpmostree-bwrap.c \
|
||||
src/libpriv/rpmostree-bwrap.h \
|
||||
src/libpriv/rpmostree-scripts.c \
|
||||
src/libpriv/rpmostree-scripts.h \
|
||||
src/libpriv/rpmostree-refsack.h \
|
||||
|
109
src/libpriv/rpmostree-bwrap.c
Normal file
109
src/libpriv/rpmostree-bwrap.c
Normal file
@ -0,0 +1,109 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Copyright (C) 2016 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the licence or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "rpmostree-bwrap.h"
|
||||
|
||||
#include <err.h>
|
||||
|
||||
void
|
||||
rpmostree_ptrarray_append_strdup (GPtrArray *argv_array, ...)
|
||||
{
|
||||
va_list args;
|
||||
char *arg;
|
||||
|
||||
va_start (args, argv_array);
|
||||
while ((arg = va_arg (args, char *)))
|
||||
g_ptr_array_add (argv_array, g_strdup (arg));
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
GPtrArray *
|
||||
rpmostree_bwrap_base_argv_new_for_rootfs (int rootfs_fd, GError **error)
|
||||
{
|
||||
g_autoptr(GPtrArray) bwrap_argv = g_ptr_array_new_with_free_func (g_free);
|
||||
static const char *usr_links[] = {"lib", "lib32", "lib64", "bin", "sbin"};
|
||||
|
||||
rpmostree_ptrarray_append_strdup (bwrap_argv,
|
||||
WITH_BUBBLEWRAP_PATH,
|
||||
"--dev", "/dev",
|
||||
"--proc", "/proc",
|
||||
"--dir", "/tmp",
|
||||
"--chdir", "/",
|
||||
"--ro-bind", "/sys/block", "/sys/block",
|
||||
"--ro-bind", "/sys/bus", "/sys/bus",
|
||||
"--ro-bind", "/sys/class", "/sys/class",
|
||||
"--ro-bind", "/sys/dev", "/sys/dev",
|
||||
"--ro-bind", "/sys/devices", "/sys/devices",
|
||||
NULL);
|
||||
|
||||
for (guint i = 0; i < G_N_ELEMENTS (usr_links); i++)
|
||||
{
|
||||
const char *subdir = usr_links[i];
|
||||
struct stat stbuf;
|
||||
char *path;
|
||||
|
||||
if (fstatat (rootfs_fd, subdir, &stbuf, AT_SYMLINK_NOFOLLOW) < 0)
|
||||
{
|
||||
if (errno != ENOENT)
|
||||
{
|
||||
glnx_set_error_from_errno (error);
|
||||
return FALSE;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (!S_ISLNK (stbuf.st_mode))
|
||||
continue;
|
||||
|
||||
g_ptr_array_add (bwrap_argv, g_strdup ("--symlink"));
|
||||
|
||||
path = g_strconcat ("usr/", subdir, NULL);
|
||||
g_ptr_array_add (bwrap_argv, path);
|
||||
|
||||
path = g_strconcat ("/", subdir, NULL);
|
||||
g_ptr_array_add (bwrap_argv, path);
|
||||
}
|
||||
|
||||
return g_steal_pointer (&bwrap_argv);
|
||||
}
|
||||
|
||||
static void
|
||||
child_setup_fchdir (gpointer user_data)
|
||||
{
|
||||
int fd = GPOINTER_TO_INT (user_data);
|
||||
if (fchdir (fd) < 0)
|
||||
err (1, "fchdir");
|
||||
}
|
||||
|
||||
gboolean
|
||||
rpmostree_run_sync_fchdir_setup (char **argv_array, GSpawnFlags flags,
|
||||
int rootfs_fd, GError **error)
|
||||
{
|
||||
int estatus;
|
||||
|
||||
if (!g_spawn_sync (NULL, argv_array, NULL, flags,
|
||||
child_setup_fchdir, GINT_TO_POINTER (rootfs_fd),
|
||||
NULL, NULL, &estatus, error))
|
||||
return FALSE;
|
||||
if (!g_spawn_check_exit_status (estatus, error))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
32
src/libpriv/rpmostree-bwrap.h
Normal file
32
src/libpriv/rpmostree-bwrap.h
Normal file
@ -0,0 +1,32 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Copyright (C) 2016 Colin Walters <walters@verbum.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the licence or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ostree.h>
|
||||
|
||||
#include "libglnx.h"
|
||||
|
||||
GPtrArray *rpmostree_bwrap_base_argv_new_for_rootfs (int rootfs, GError **error);
|
||||
|
||||
void rpmostree_ptrarray_append_strdup (GPtrArray *argv_array, ...) G_GNUC_NULL_TERMINATED;
|
||||
|
||||
gboolean rpmostree_run_sync_fchdir_setup (char **argv_array, GSpawnFlags flags,
|
||||
int rootfs_fd, GError **error);
|
@ -23,6 +23,7 @@
|
||||
#include <gio/gio.h>
|
||||
#include <systemd/sd-journal.h>
|
||||
#include "rpmostree-output.h"
|
||||
#include "rpmostree-bwrap.h"
|
||||
#include <err.h>
|
||||
#include "libglnx.h"
|
||||
|
||||
@ -73,26 +74,6 @@ static const KnownRpmScriptKind unsupported_scripts[] = {
|
||||
RPMTAG_VERIFYSCRIPT, RPMTAG_VERIFYSCRIPTPROG, RPMTAG_VERIFYSCRIPTFLAGS},
|
||||
};
|
||||
|
||||
static void
|
||||
child_setup_fchdir (gpointer user_data)
|
||||
{
|
||||
int fd = GPOINTER_TO_INT (user_data);
|
||||
if (fchdir (fd) < 0)
|
||||
err (1, "fchdir");
|
||||
}
|
||||
|
||||
static void
|
||||
add_const_args (GPtrArray *argv_array, ...)
|
||||
{
|
||||
va_list args;
|
||||
char *arg;
|
||||
|
||||
va_start (args, argv_array);
|
||||
while ((arg = va_arg (args, char *)))
|
||||
g_ptr_array_add (argv_array, arg);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
static void
|
||||
fusermount_cleanup (const char *mountpoint)
|
||||
{
|
||||
@ -188,9 +169,6 @@ run_script_in_bwrap_container (int rootfs_fd,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
int i;
|
||||
const char *usr_links[] = {"lib", "lib32", "lib64", "bin", "sbin"};
|
||||
int estatus;
|
||||
char *rofiles_mnt = strdupa ("/tmp/rofiles-fuse.XXXXXX");
|
||||
const char *rofiles_argv[] = { "rofiles-fuse", "./usr", rofiles_mnt, NULL};
|
||||
const char *pkg_script = glnx_strjoina (name, ".", scriptdesc+1);
|
||||
@ -200,7 +178,6 @@ run_script_in_bwrap_container (int rootfs_fd,
|
||||
gboolean mntpoint_created = FALSE;
|
||||
gboolean fuse_mounted = FALSE;
|
||||
g_autoptr(GPtrArray) bwrap_argv = g_ptr_array_new ();
|
||||
g_autoptr(GPtrArray) bwrap_argv_mallocd = g_ptr_array_new_with_free_func (g_free);
|
||||
GSpawnFlags bwrap_spawnflags = G_SPAWN_SEARCH_PATH;
|
||||
gboolean created_var_tmp = FALSE;
|
||||
|
||||
@ -209,11 +186,8 @@ run_script_in_bwrap_container (int rootfs_fd,
|
||||
|
||||
mntpoint_created = TRUE;
|
||||
|
||||
if (!g_spawn_sync (NULL, (char**)rofiles_argv, NULL, G_SPAWN_SEARCH_PATH,
|
||||
child_setup_fchdir, GINT_TO_POINTER (rootfs_fd),
|
||||
NULL, NULL, &estatus, error))
|
||||
goto out;
|
||||
if (!g_spawn_check_exit_status (estatus, error))
|
||||
if (!rpmostree_run_sync_fchdir_setup ((char**)rofiles_argv, G_SPAWN_SEARCH_PATH,
|
||||
rootfs_fd, error))
|
||||
{
|
||||
g_prefix_error (error, "Executing rofiles-fuse: ");
|
||||
goto out;
|
||||
@ -260,65 +234,33 @@ run_script_in_bwrap_container (int rootfs_fd,
|
||||
else
|
||||
created_var_tmp = TRUE;
|
||||
|
||||
add_const_args (bwrap_argv,
|
||||
WITH_BUBBLEWRAP_PATH,
|
||||
bwrap_argv = rpmostree_bwrap_base_argv_new_for_rootfs (rootfs_fd, error);
|
||||
if (!bwrap_argv)
|
||||
goto out;
|
||||
|
||||
rpmostree_ptrarray_append_strdup (bwrap_argv,
|
||||
"--bind", rofiles_mnt, "/usr",
|
||||
"--dev", "/dev",
|
||||
"--proc", "/proc",
|
||||
"--dir", "/tmp",
|
||||
"--chdir", "/",
|
||||
/* Scripts can see a /var with compat links like alternatives */
|
||||
"--ro-bind", "./var", "/var",
|
||||
/* But no need to access persistent /tmp, so make it /tmp */
|
||||
"--bind", "/tmp", "/var/tmp",
|
||||
/* Allow RPM scripts to change the /etc defaults */
|
||||
"--symlink", "usr/etc", "/etc",
|
||||
"--ro-bind", "/sys/block", "/sys/block",
|
||||
"--ro-bind", "/sys/bus", "/sys/bus",
|
||||
"--ro-bind", "/sys/class", "/sys/class",
|
||||
"--ro-bind", "/sys/dev", "/sys/dev",
|
||||
"--ro-bind", "/sys/devices", "/sys/devices",
|
||||
NULL);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (usr_links); i++)
|
||||
{
|
||||
const char *subdir = usr_links[i];
|
||||
struct stat stbuf;
|
||||
char *path;
|
||||
|
||||
if (!(fstatat (rootfs_fd, subdir, &stbuf, AT_SYMLINK_NOFOLLOW) == 0 && S_ISLNK (stbuf.st_mode)))
|
||||
continue;
|
||||
|
||||
g_ptr_array_add (bwrap_argv, "--symlink");
|
||||
|
||||
path = g_strconcat ("usr/", subdir, NULL);
|
||||
g_ptr_array_add (bwrap_argv_mallocd, path);
|
||||
g_ptr_array_add (bwrap_argv, path);
|
||||
|
||||
path = g_strconcat ("/", subdir, NULL);
|
||||
g_ptr_array_add (bwrap_argv_mallocd, path);
|
||||
g_ptr_array_add (bwrap_argv, path);
|
||||
}
|
||||
|
||||
{ const char *debugscript = getenv ("RPMOSTREE_DEBUG_SCRIPT");
|
||||
if (g_strcmp0 (debugscript, pkg_script) == 0)
|
||||
{
|
||||
g_ptr_array_add (bwrap_argv, (char*)"/bin/bash");
|
||||
g_ptr_array_add (bwrap_argv, g_strdup ("/bin/bash"));
|
||||
bwrap_spawnflags |= G_SPAWN_CHILD_INHERITS_STDIN;
|
||||
}
|
||||
else
|
||||
g_ptr_array_add (bwrap_argv, (char*)postscript_path_container);
|
||||
g_ptr_array_add (bwrap_argv, g_strdup (postscript_path_container));
|
||||
}
|
||||
g_ptr_array_add (bwrap_argv, NULL);
|
||||
|
||||
if (!g_spawn_sync (NULL, (char**)bwrap_argv->pdata, NULL, bwrap_spawnflags,
|
||||
child_setup_fchdir, GINT_TO_POINTER (rootfs_fd),
|
||||
NULL, NULL, &estatus, error))
|
||||
{
|
||||
g_prefix_error (error, "Executing bwrap: ");
|
||||
goto out;
|
||||
}
|
||||
if (!g_spawn_check_exit_status (estatus, error))
|
||||
if (!rpmostree_run_sync_fchdir_setup ((char**)bwrap_argv->pdata,
|
||||
bwrap_spawnflags, rootfs_fd, error))
|
||||
{
|
||||
g_prefix_error (error, "Executing bwrap: ");
|
||||
goto out;
|
||||
|
Loading…
Reference in New Issue
Block a user