summaryrefslogtreecommitdiff
path: root/common/flatpak-exports.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/flatpak-exports.c')
-rw-r--r--common/flatpak-exports.c172
1 files changed, 152 insertions, 20 deletions
diff --git a/common/flatpak-exports.c b/common/flatpak-exports.c
index 6ac9dd46..15acc5b8 100644
--- a/common/flatpak-exports.c
+++ b/common/flatpak-exports.c
@@ -1,4 +1,4 @@
-/*
+/* vi:set et sw=2 sts=2 cin cino=t0,f0,(0,{s,>2s,n-s,^-s,e-s:
* Copyright © 2014-2019 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
@@ -93,6 +93,40 @@ is_export_mode (int mode)
|| mode == FAKE_MODE_SYMLINK);
}
+static inline const char *
+export_mode_to_verb (int mode)
+{
+ switch (mode)
+ {
+ case FAKE_MODE_DIR:
+ return "ensure existence of directory";
+
+ case FAKE_MODE_SYMLINK:
+ return "create symbolic link";
+
+ default:
+ break;
+ }
+
+ switch ((FlatpakFilesystemMode) mode)
+ {
+ case FLATPAK_FILESYSTEM_MODE_READ_ONLY:
+ return "export read-only";
+
+ case FLATPAK_FILESYSTEM_MODE_CREATE:
+ return "create and export read/write";
+
+ case FLATPAK_FILESYSTEM_MODE_READ_WRITE:
+ return "export read/write";
+
+ case FLATPAK_FILESYSTEM_MODE_NONE:
+ return "replace with tmpfs";
+
+ default:
+ return "[use unknown/invalid mode?]";
+ }
+}
+
typedef struct
{
char *path;
@@ -394,6 +428,8 @@ flatpak_exports_append_bwrap_args (FlatpakExports *exports,
g_qsort_with_data (keys, n_keys, sizeof (char *), (GCompareDataFunc) flatpak_strcmp0_ptr, NULL);
+ g_debug ("Converting FlatpakExports to bwrap arguments...");
+
for (l = eps; l != NULL; l = l->next)
{
ExportedPath *ep = l->data;
@@ -403,7 +439,14 @@ flatpak_exports_append_bwrap_args (FlatpakExports *exports,
if (ep->mode == FAKE_MODE_SYMLINK)
{
- if (!path_parent_is_mapped (keys, n_keys, exports->hash, path))
+ g_debug ("\"%s\" is meant to be a symlink", path);
+
+ if (path_parent_is_mapped (keys, n_keys, exports->hash, path))
+ {
+ g_debug ("Not creating \"%s\" as symlink because its parent is "
+ "already mapped", path);
+ }
+ else
{
g_autofree char *resolved = flatpak_exports_resolve_link_in_host (exports,
path,
@@ -412,30 +455,60 @@ flatpak_exports_append_bwrap_args (FlatpakExports *exports,
{
g_autofree char *parent = g_path_get_dirname (path);
g_autofree char *relative = make_relative (parent, resolved);
+
+ g_debug ("Resolved \"%s\" to \"%s\" in host", path, resolved);
+ g_debug ("Creating \"%s\" -> \"%s\" in sandbox", path, relative);
flatpak_bwrap_add_args (bwrap, "--symlink", relative, path, NULL);
}
+ else
+ {
+ g_debug ("Unable to resolve \"%s\" in host, skipping", path);
+ }
}
}
else if (ep->mode == FAKE_MODE_TMPFS)
{
+ g_debug ("\"%s\" is meant to be a tmpfs or empty directory", path);
+
/* Mount a tmpfs to hide the subdirectory, but only if there
is a pre-existing dir we can mount the path on. */
if (path_is_dir (exports, path))
{
if (!path_parent_is_mapped (keys, n_keys, exports->hash, path))
/* If the parent is not mapped, it will be a tmpfs, no need to mount another one */
- flatpak_bwrap_add_args (bwrap, "--dir", path, NULL);
+ {
+ g_debug ("Parent of \"%s\" is not mapped, creating empty directory", path);
+ flatpak_bwrap_add_args (bwrap, "--dir", path, NULL);
+ }
else
- flatpak_bwrap_add_args (bwrap, "--tmpfs", path, NULL);
+ {
+ g_debug ("Parent of \"%s\" is mapped, creating tmpfs to shadow it", path);
+ flatpak_bwrap_add_args (bwrap, "--tmpfs", path, NULL);
+ }
+ }
+ else
+ {
+ g_debug ("Not a directory, skipping: \"%s\"", path);
}
}
else if (ep->mode == FAKE_MODE_DIR)
{
+ g_debug ("\"%s\" is meant to be a directory", path);
+
if (path_is_dir (exports, path))
- flatpak_bwrap_add_args (bwrap, "--dir", path, NULL);
+ {
+ g_debug ("Ensuring \"%s\" is created as a directory", path);
+ flatpak_bwrap_add_args (bwrap, "--dir", path, NULL);
+ }
+ else
+ {
+ g_debug ("Not a directory, skipping: \"%s\"", path);
+ }
}
else
{
+ g_debug ("\"%s\" is meant to be shared (ro or rw) with the container",
+ path);
flatpak_bwrap_add_args (bwrap,
(ep->mode == FLATPAK_FILESYSTEM_MODE_READ_ONLY) ? "--ro-bind" : "--bind",
path, path, NULL);
@@ -679,9 +752,29 @@ do_export_path (FlatpakExports *exports,
ep->path = g_strdup (path);
if (old_ep != NULL)
- ep->mode = MAX (old_ep->mode, mode);
+ {
+ if (old_ep->mode < mode)
+ {
+ g_debug ("Increasing export mode from \"%s\" to \"%s\": %s",
+ export_mode_to_verb (old_ep->mode),
+ export_mode_to_verb (mode),
+ path);
+ ep->mode = mode;
+ }
+ else
+ {
+ g_debug ("Not changing export mode from \"%s\" to \"%s\": %s",
+ export_mode_to_verb (old_ep->mode),
+ export_mode_to_verb (mode),
+ path);
+ ep->mode = old_ep->mode;
+ }
+ }
else
- ep->mode = mode;
+ {
+ g_debug ("Will %s: %s", export_mode_to_verb (mode), path);
+ ep->mode = mode;
+ }
g_hash_table_replace (exports->hash, ep->path, ep);
}
@@ -784,36 +877,53 @@ _exports_path_expose (FlatpakExports *exports,
g_return_val_if_fail (is_export_mode (mode), FALSE);
+ g_debug ("Trying to %s: %s", export_mode_to_verb (mode), path);
+
if (level > 40) /* 40 is the current kernel ELOOP check */
{
- g_debug ("Expose too deep, bail");
+ g_info ("Expose too deep, bail");
return FALSE;
}
if (!g_path_is_absolute (path))
{
- g_debug ("Not exposing relative path %s", path);
+ g_info ("Not exposing relative path %s", path);
return FALSE;
}
/* Check if it exists at all */
o_path_fd = flatpak_exports_open_in_host (exports, path, O_PATH | O_NOFOLLOW);
+
if (o_path_fd == -1)
- return FALSE;
+ {
+ g_info ("Unable to open path %s to %s: %s",
+ path, export_mode_to_verb (mode), g_strerror (errno));
+ return FALSE;
+ }
if (fstat (o_path_fd, &st) != 0)
- return FALSE;
+ {
+ g_info ("Unable to get file type of %s: %s", path, g_strerror (errno));
+ return FALSE;
+ }
/* Don't expose weird things */
if (!(S_ISDIR (st.st_mode) ||
S_ISREG (st.st_mode) ||
S_ISLNK (st.st_mode) ||
S_ISSOCK (st.st_mode)))
- return FALSE;
+ {
+ g_info ("%s has unsupported file type 0o%o", path, st.st_mode & S_IFMT);
+ return FALSE;
+ }
/* O_PATH + fstatfs is the magic that we need to statfs without automounting the target */
if (fstatfs (o_path_fd, &stfs) != 0)
- return FALSE;
+ {
+ g_info ("Unable to get filesystem information for %s: %s",
+ path, g_strerror (errno));
+ return FALSE;
+ }
if (stfs.f_type == AUTOFS_SUPER_MAGIC ||
(G_UNLIKELY (exports->test_flags & FLATPAK_EXPORTS_TEST_FLAGS_AUTOFS) &&
@@ -821,7 +931,7 @@ _exports_path_expose (FlatpakExports *exports,
{
if (!check_if_autofs_works (exports, path))
{
- g_debug ("ignoring blocking autofs path %s", path);
+ g_info ("ignoring blocking autofs path %s", path);
return FALSE;
}
}
@@ -836,7 +946,7 @@ _exports_path_expose (FlatpakExports *exports,
create the parents for them anyway */
if (flatpak_has_path_prefix (path, dont_export_in[i]))
{
- g_debug ("skipping export for path %s", path);
+ g_info ("skipping export for path %s in unsupported prefix", path);
return FALSE;
}
}
@@ -846,7 +956,7 @@ _exports_path_expose (FlatpakExports *exports,
/* Same as /usr, but for the directories that get merged into /usr */
if (flatpak_has_path_prefix (path, flatpak_abs_usrmerged_dirs[i]))
{
- g_debug ("skipping export for path %s", path);
+ g_info ("skipping export for path %s in a /usr-merged directory", path);
return FALSE;
}
}
@@ -860,27 +970,49 @@ _exports_path_expose (FlatpakExports *exports,
if (slash)
*slash = 0;
- if (path_is_symlink (exports, path) && !never_export_as_symlink (path))
+ if (!path_is_symlink (exports, path))
+ {
+ g_debug ("%s is not a symlink", path);
+ }
+ else if (never_export_as_symlink (path))
+ {
+ g_debug ("%s is a symlink, but we avoid exporting it as such", path);
+ }
+ else
{
- g_autofree char *resolved = flatpak_exports_resolve_link_in_host (exports, path, NULL);
+ g_autoptr(GError) error = NULL;
+ g_autofree char *resolved = flatpak_exports_resolve_link_in_host (exports, path, &error);
g_autofree char *new_target = NULL;
if (resolved)
{
+ g_debug ("%s is a symlink, resolved to %s", path, resolved);
+
if (slash)
new_target = g_build_filename (resolved, slash + 1, NULL);
else
new_target = g_strdup (resolved);
+ g_debug ("Trying to export the target instead: %s", new_target);
+
if (_exports_path_expose (exports, mode, new_target, level + 1))
{
do_export_path (exports, path, FAKE_MODE_SYMLINK);
return TRUE;
}
- }
- return FALSE;
+ g_debug ("Could not export target %s, so ignoring %s",
+ new_target, path);
+ return FALSE;
+ }
+ else
+ {
+ g_debug ("%s is a symlink but we were unable to resolve it: %s",
+ path, error->message);
+ return FALSE;
+ }
}
+
if (slash)
*slash = '/';
}