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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list