In order to be able to mount a custom host-image as / we need to be able
to access libvirt-sandbox-init-common and all its needed dependencies.
In the container case we also need to copy libvirt-sandbox-init-lxc.
They are now copied into SANDBOXCONFIGDIR /.libs. Hard linking is not
possible since we may be working on separate partitions, and symlinks
wouldn't help to work with apparmor. Copying makes apparmor happy and
solves our problem.
---
configure.ac | 7 +
.../libvirt-sandbox-builder-container.c | 15 +-
libvirt-sandbox/libvirt-sandbox-builder.c | 159 ++++++++++++++++++++-
libvirt-sandbox/libvirt-sandbox-builder.h | 2 +
libvirt-sandbox/libvirt-sandbox-init-lxc.c | 8 +-
libvirt-sandbox/libvirt-sandbox-init-qemu.c | 9 +-
6 files changed, 196 insertions(+), 4 deletions(-)
diff --git a/configure.ac b/configure.ac
index 99d22d7..608f56b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -109,6 +109,13 @@ LIBVIRT_SANDBOX_SELINUX
LIBVIRT_SANDBOX_STATIC_LIBC
+dnl search for LDD path
+AC_PATH_PROG([LDD_PATH], [ldd])
+if test -z "$LDD_PATH"; then
+ AC_MSG_ERROR([Failed to find ldd.])
+fi
+AC_DEFINE_UNQUOTED([LDD_PATH], "$LDD_PATH", [path to ldd binary])
+
GOBJECT_INTROSPECTION_CHECK([$GOBJECT_INTROSPECTION_REQUIRED])
dnl Should be in m4/virt-gettext.m4 but intltoolize is too
diff --git a/libvirt-sandbox/libvirt-sandbox-builder-container.c
b/libvirt-sandbox/libvirt-sandbox-builder-container.c
index c23b82b..d226d35 100644
--- a/libvirt-sandbox/libvirt-sandbox-builder-container.c
+++ b/libvirt-sandbox/libvirt-sandbox-builder-container.c
@@ -184,7 +184,7 @@ static gboolean
gvir_sandbox_builder_container_construct_os(GVirSandboxBuilder *
gvir_config_domain_os_set_arch(os,
gvir_sandbox_config_get_arch(config));
gvir_config_domain_os_set_init(os,
- LIBEXECDIR "/libvirt-sandbox-init-lxc");
+ SANDBOXCONFIGDIR
"/.libs/libvirt-sandbox-init-lxc");
gvir_config_domain_os_set_cmdline(os, cmdline);
gvir_config_domain_set_os(domain, os);
@@ -444,6 +444,18 @@ static const gchar
*gvir_sandbox_builder_container_get_disk_prefix(GVirSandboxBu
return "sd";
}
+
+static GList *gvir_sandbox_builder_container_get_files_to_copy(GVirSandboxBuilder
*builder,
+ GVirSandboxConfig *config
G_GNUC_UNUSED)
+{
+ GList * tocopy =
GVIR_SANDBOX_BUILDER_CLASS(gvir_sandbox_builder_container_parent_class)->
+ get_files_to_copy(builder, config);
+ gchar *file = g_strdup_printf("%s/libvirt-sandbox-init-lxc", LIBEXECDIR);
+
+ return g_list_append(tocopy, file);
+}
+
+
static void gvir_sandbox_builder_container_class_init(GVirSandboxBuilderContainerClass
*klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
@@ -458,6 +470,7 @@ static void
gvir_sandbox_builder_container_class_init(GVirSandboxBuilderContaine
builder_class->construct_features =
gvir_sandbox_builder_container_construct_features;
builder_class->construct_devices =
gvir_sandbox_builder_container_construct_devices;
builder_class->get_disk_prefix = gvir_sandbox_builder_container_get_disk_prefix;
+ builder_class->get_files_to_copy =
gvir_sandbox_builder_container_get_files_to_copy;
g_type_class_add_private(klass, sizeof(GVirSandboxBuilderContainerPrivate));
}
diff --git a/libvirt-sandbox/libvirt-sandbox-builder.c
b/libvirt-sandbox/libvirt-sandbox-builder.c
index aa932db..2726868 100644
--- a/libvirt-sandbox/libvirt-sandbox-builder.c
+++ b/libvirt-sandbox/libvirt-sandbox-builder.c
@@ -107,6 +107,8 @@ static gboolean
gvir_sandbox_builder_clean_post_stop_default(GVirSandboxBuilder
GVirSandboxConfig *config,
const gchar *statedir,
GError **error);
+static GList *gvir_sandbox_builder_get_files_to_copy(GVirSandboxBuilder *builder,
+ GVirSandboxConfig *config);
static void gvir_sandbox_builder_get_property(GObject *object,
guint prop_id,
@@ -176,6 +178,7 @@ static void gvir_sandbox_builder_class_init(GVirSandboxBuilderClass
*klass)
klass->construct_security = gvir_sandbox_builder_construct_security;
klass->clean_post_start = gvir_sandbox_builder_clean_post_start_default;
klass->clean_post_stop = gvir_sandbox_builder_clean_post_stop_default;
+ klass->get_files_to_copy = gvir_sandbox_builder_get_files_to_copy;
g_object_class_install_property(object_class,
PROP_CONNECTION,
@@ -247,6 +250,108 @@ GVirConnection
*gvir_sandbox_builder_get_connection(GVirSandboxBuilder *builder)
}
+static gboolean gvir_sandbox_builder_copy_file(const char *path,
+ const char *libsdir,
+ GError **error)
+{
+ gchar *name = g_path_get_basename(path);
+ gchar *target = g_build_filename(libsdir, name, NULL);
+ GFile *srcFile = g_file_new_for_path(path);
+ GFile *tgtFile = g_file_new_for_path(target);
+ gboolean result = FALSE;
+
+
+ if (!g_file_query_exists(tgtFile, NULL) &&
+ !g_file_copy(srcFile, tgtFile, 0, NULL, NULL, NULL, error))
+ goto cleanup;
+
+ result = TRUE;
+
+ cleanup:
+ g_object_unref(tgtFile);
+ g_object_unref(srcFile);
+ g_free(target);
+ g_free(name);
+
+ return result;
+}
+
+static gboolean gvir_sandbox_builder_copy_program(const char *program,
+ const char *dest,
+ GError **error)
+{
+ gchar *out = NULL;
+ gchar *line, *tmp;
+ const gchar *argv[] = {LDD_PATH, program, NULL};
+ gboolean result = FALSE;
+
+ if (!gvir_sandbox_builder_copy_file(program, dest, error))
+ goto cleanup;
+
+
+ /* Get all the dependencies to be hard linked */
+ if (!g_spawn_sync(NULL, (gchar **)argv, NULL, 0,
+ NULL, NULL, &out, NULL, NULL, error))
+ goto cleanup;
+
+ /* Loop over the output lines to get the path to the libraries to copy */
+ line = out;
+ while ((tmp = strchr(line, '\n'))) {
+ gchar *start, *end;
+ *tmp = '\0';
+
+ /* Search the line for the library path */
+ start = strstr(line, " => ");
+ end = strstr(line, " (");
+
+ if (start && end) {
+ start = start + 4;
+ *end = '\0';
+
+ if (!gvir_sandbox_builder_copy_file(start, dest, error))
+ goto cleanup;
+ }
+
+ line = tmp + 1;
+ }
+ result = TRUE;
+
+ cleanup:
+ g_free(out);
+
+ return result;
+}
+
+static gboolean gvir_sandbox_builder_copy_init(GVirSandboxBuilder *builder,
+ GVirSandboxConfig *config,
+ const gchar *statedir,
+ GError **error)
+{
+ gchar *libsdir;
+ GVirSandboxBuilderClass *klass = GVIR_SANDBOX_BUILDER_GET_CLASS(builder);
+ GList *tocopy = NULL, *tmp = NULL;
+ gboolean result = FALSE;
+
+ libsdir = g_build_filename(statedir, "config", ".libs", NULL);
+ g_mkdir_with_parents(libsdir, 0755);
+
+ tmp = tocopy = klass->get_files_to_copy(builder, config);
+ while (tmp) {
+ if (!gvir_sandbox_builder_copy_program(tmp->data, libsdir, error))
+ goto cleanup;
+
+ tmp = tmp->next;
+ }
+ result = TRUE;
+
+ cleanup:
+ g_free(libsdir);
+ g_list_free_full(tocopy, g_free);
+
+ return result;
+}
+
+
static gboolean gvir_sandbox_builder_construct_domain(GVirSandboxBuilder *builder,
GVirSandboxConfig *config,
const gchar *statedir,
@@ -255,6 +360,9 @@ static gboolean
gvir_sandbox_builder_construct_domain(GVirSandboxBuilder *builde
{
GVirSandboxBuilderClass *klass = GVIR_SANDBOX_BUILDER_GET_CLASS(builder);
+ if (!gvir_sandbox_builder_copy_init(builder, config, statedir, error))
+ return FALSE;
+
if (!(klass->construct_basic(builder, config, statedir, domain, error)))
return FALSE;
@@ -511,6 +619,15 @@ static gboolean
gvir_sandbox_builder_clean_post_stop_default(GVirSandboxBuilder
return TRUE;
}
+static GList *gvir_sandbox_builder_get_files_to_copy(GVirSandboxBuilder *builder,
+ GVirSandboxConfig *config
G_GNUC_UNUSED)
+{
+ GList *tocopy = NULL;
+ gchar *file = g_strdup_printf("%s/libvirt-sandbox-init-common",
LIBEXECDIR);
+ return g_list_append(tocopy, file);
+}
+
+
/**
* gvir_sandbox_builder_construct:
* @builder: (transfer none): the sandbox builder
@@ -577,8 +694,48 @@ gboolean gvir_sandbox_builder_clean_post_stop(GVirSandboxBuilder
*builder,
GError **error)
{
GVirSandboxBuilderClass *klass = GVIR_SANDBOX_BUILDER_GET_CLASS(builder);
+ gchar *libsdir = g_build_filename(statedir, "config", ".libs",
NULL);
+ GFile *libsFile = g_file_new_for_path(libsdir);
+ GFileEnumerator *enumerator = NULL;
+ GFileInfo *info = NULL;
+ GFile *child = NULL;
+ gboolean ret = TRUE;
+
+ ret = klass->clean_post_stop(builder, config, statedir, error);
+
+ if (!(enumerator = g_file_enumerate_children(libsFile, "*",
G_FILE_QUERY_INFO_NONE,
+ NULL, error)) &&
+ (*error)->code != G_IO_ERROR_NOT_FOUND) {
+ ret = FALSE;
+ goto cleanup;
+ }
+
+ while ((info = g_file_enumerator_next_file(enumerator, NULL, error))) {
+ child = g_file_enumerator_get_child(enumerator, info);
+ if (!g_file_delete(child, NULL, error))
+ ret = FALSE;
+ g_object_unref(child);
+ child = NULL;
+ g_object_unref(info);
+ info = NULL;
+ }
+
+ if (!g_file_enumerator_close(enumerator, NULL, error))
+ ret = FALSE;
- return klass->clean_post_stop(builder, config, statedir, error);
+ if (!g_file_delete(libsFile, NULL, error) &&
+ (*error)->code != G_IO_ERROR_NOT_FOUND)
+ ret = FALSE;
+
+ cleanup:
+ if (child)
+ g_object_unref(child);
+ if (info)
+ g_object_unref(info);
+ g_object_unref(enumerator);
+ g_object_unref(libsFile);
+ g_free(libsdir);
+ return ret;
}
diff --git a/libvirt-sandbox/libvirt-sandbox-builder.h
b/libvirt-sandbox/libvirt-sandbox-builder.h
index 81df92a..2d22f1a 100644
--- a/libvirt-sandbox/libvirt-sandbox-builder.h
+++ b/libvirt-sandbox/libvirt-sandbox-builder.h
@@ -97,6 +97,8 @@ struct _GVirSandboxBuilderClass
const gchar *(*get_disk_prefix)(GVirSandboxBuilder *builder,
GVirSandboxConfig *config,
GVirSandboxConfigDisk *disk);
+ GList *(*get_files_to_copy)(GVirSandboxBuilder *builder,
+ GVirSandboxConfig *config);
gpointer padding[LIBVIRT_SANDBOX_CLASS_PADDING];
};
diff --git a/libvirt-sandbox/libvirt-sandbox-init-lxc.c
b/libvirt-sandbox/libvirt-sandbox-init-lxc.c
index 798af37..e2fe7f0 100644
--- a/libvirt-sandbox/libvirt-sandbox-init-lxc.c
+++ b/libvirt-sandbox/libvirt-sandbox-init-lxc.c
@@ -77,10 +77,16 @@ main(int argc, char **argv)
args[narg++] = "1000";
}
- args[narg++] = LIBEXECDIR "/libvirt-sandbox-init-common";
+ args[narg++] = SANDBOXCONFIGDIR "/.libs/libvirt-sandbox-init-common";
if (debug)
args[narg++] = "-d";
+ if (setenv("LD_LIBRARY_PATH", SANDBOXCONFIGDIR "/.libs", 1) != 0)
{
+ fprintf(stderr, "libvirt-sandbox-init-lxc: %s: cannot set LD_LIBRARY_PATH:
%s\n",
+ __func__, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
if (debug)
fprintf(stderr, "Running interactive\n");
execv(args[0], (char**)args);
diff --git a/libvirt-sandbox/libvirt-sandbox-init-qemu.c
b/libvirt-sandbox/libvirt-sandbox-init-qemu.c
index 44305fd..62e8e40 100644
--- a/libvirt-sandbox/libvirt-sandbox-init-qemu.c
+++ b/libvirt-sandbox/libvirt-sandbox-init-qemu.c
@@ -338,10 +338,17 @@ main(int argc ATTR_UNUSED, char **argv ATTR_UNUSED)
args[narg++] = "1000";
}
- args[narg++] = LIBEXECDIR "/libvirt-sandbox-init-common";
+ args[narg++] = SANDBOXCONFIGDIR "/.libs/libvirt-sandbox-init-common";
if (debug)
args[narg++] = "-d";
+ if (setenv("LD_LIBRARY_PATH", SANDBOXCONFIGDIR "/.libs", 1) <
0) {
+ fprintf(stderr, "libvirt-sandbox-init-qemu: %s: cannot set LD_LIBRARY_PATH:
%s\n",
+ __func__, strerror(errno));
+ exit_poweroff();
+ }
+
+
if (debug)
fprintf(stderr, "libvirt-sandbox-init-qemu: Running common init %s\n",
args[0]);
execv(args[0], (char**)args);
--
2.1.4