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.
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/libvirt-sandbox-builder-machine.c | 114 ++++++++++++++++++++++
libvirt-sandbox/libvirt-sandbox-init-qemu.c | 5 +-
3 files changed, 124 insertions(+), 2 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-machine.c
b/libvirt-sandbox/libvirt-sandbox-builder-machine.c
index 17a2afe..7a2af83 100644
--- a/libvirt-sandbox/libvirt-sandbox-builder-machine.c
+++ b/libvirt-sandbox/libvirt-sandbox-builder-machine.c
@@ -358,6 +358,81 @@ static gboolean
gvir_sandbox_builder_machine_write_mount_cfg(GVirSandboxConfig *
return ret;
}
+static gboolean gvir_sandbox_builder_machine_copy_lib(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_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_machine_copy_init(const gchar *statedir,
+ GError **error)
+{
+ gchar *libsdir;
+ const gchar *initPath = LIBEXECDIR "/libvirt-sandbox-init-common";
+ gchar *out = NULL;
+ gchar *line, *tmp;
+ const gchar *argv[] = {LDD_PATH, initPath, NULL};
+ gboolean result = FALSE;
+
+ libsdir = g_build_filename(statedir, "config", ".libs", NULL);
+
+ g_mkdir_with_parents(libsdir, 0755);
+
+ if (!gvir_sandbox_builder_machine_copy_lib(initPath, libsdir, 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 hard link */
+ 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_machine_copy_lib(start, libsdir, error))
+ goto cleanup;
+ }
+
+ line = tmp + 1;
+ }
+ result = TRUE;
+
+ cleanup:
+ g_free(libsdir);
+ g_free(out);
+
+ return result;
+}
static gboolean gvir_sandbox_builder_machine_construct_domain(GVirSandboxBuilder
*builder,
GVirSandboxConfig *config,
@@ -370,6 +445,9 @@ static gboolean
gvir_sandbox_builder_machine_construct_domain(GVirSandboxBuilder
error))
return FALSE;
+ if (!gvir_sandbox_builder_machine_copy_init(statedir, error))
+ return FALSE;
+
if (!GVIR_SANDBOX_BUILDER_CLASS(gvir_sandbox_builder_machine_parent_class)->
construct_domain(builder, config, statedir, domain, error))
return FALSE;
@@ -712,12 +790,48 @@ static gboolean
gvir_sandbox_builder_machine_clean_post_stop(GVirSandboxBuilder
GError **error)
{
gchar *mntfile = g_strdup_printf("%s/config/mounts.cfg", statedir);
+ 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;
if (unlink(mntfile) < 0 &&
errno != ENOENT)
ret = FALSE;
+ 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;
+
+ 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);
g_free(mntfile);
return ret;
}
diff --git a/libvirt-sandbox/libvirt-sandbox-init-qemu.c
b/libvirt-sandbox/libvirt-sandbox-init-qemu.c
index db67fdb..45cb9b3 100644
--- a/libvirt-sandbox/libvirt-sandbox-init-qemu.c
+++ b/libvirt-sandbox/libvirt-sandbox-init-qemu.c
@@ -230,6 +230,7 @@ int
main(int argc ATTR_UNUSED, char **argv ATTR_UNUSED)
{
const char *args[50];
+ const char *env[] = {"LD_LIBRARY_PATH=" SANDBOXCONFIGDIR
"/.libs", NULL};
int narg = 0;
char *strace = NULL;
@@ -430,13 +431,13 @@ 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 (debug)
fprintf(stderr, "libvirt-sandbox-init-qemu: Running common init %s\n",
args[0]);
- execv(args[0], (char**)args);
+ execve(args[0], (char**)args, (char**)env);
fprintf(stderr, "libvirt-sandbox-init-qemu: %s: cannot execute %s: %s\n",
__func__, args[0], strerror(errno));
exit_poweroff();
--
2.1.4