mirror of
https://github.com/flatpak/flatpak.git
synced 2026-04-03 23:04:49 -04:00
exports: Make _exports_path_expose produce a GError on failure
This is a step towards allowing its direct and indirect callers to decide
how serious the failure is, and debug or warn accordingly.
Helps: https://github.com/flatpak/flatpak/issues/5205
Signed-off-by: Simon McVittie <smcv@collabora.com>
(cherry picked from commit 1b49de1890)
This commit is contained in:
@@ -869,12 +869,18 @@ check_if_autofs_works (FlatpakExports *exports,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We use level to avoid infinite recursion */
|
/* We use level to avoid infinite recursion.
|
||||||
|
*
|
||||||
|
* Note that some of the errors produced by this function are "real errors"
|
||||||
|
* and should show up as a user-visible warning, but others are relatively
|
||||||
|
* uninteresting, and in general none are actually fatal: we prefer to
|
||||||
|
* continue with fewer paths exposed rather than failing to run. */
|
||||||
static gboolean
|
static gboolean
|
||||||
_exports_path_expose (FlatpakExports *exports,
|
_exports_path_expose (FlatpakExports *exports,
|
||||||
int mode,
|
int mode,
|
||||||
const char *path,
|
const char *path,
|
||||||
int level)
|
int level,
|
||||||
|
GError **error)
|
||||||
{
|
{
|
||||||
g_autofree char *canonical = NULL;
|
g_autofree char *canonical = NULL;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
@@ -889,13 +895,15 @@ _exports_path_expose (FlatpakExports *exports,
|
|||||||
|
|
||||||
if (level > 40) /* 40 is the current kernel ELOOP check */
|
if (level > 40) /* 40 is the current kernel ELOOP check */
|
||||||
{
|
{
|
||||||
g_debug ("Expose too deep, bail");
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_TOO_MANY_LINKS,
|
||||||
|
"%s", g_strerror (ELOOP));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!g_path_is_absolute (path))
|
if (!g_path_is_absolute (path))
|
||||||
{
|
{
|
||||||
g_debug ("Not exposing relative path %s", path);
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_FILENAME,
|
||||||
|
_("An absolute path is required"));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -904,34 +912,38 @@ _exports_path_expose (FlatpakExports *exports,
|
|||||||
|
|
||||||
if (o_path_fd == -1)
|
if (o_path_fd == -1)
|
||||||
{
|
{
|
||||||
g_debug ("Unable to open path %s to %s: %s",
|
int saved_errno = errno;
|
||||||
path, export_mode_to_verb (mode), g_strerror (errno));
|
|
||||||
|
/* Intentionally using G_IO_ERROR_NOT_FOUND even if errno is
|
||||||
|
* something different, so callers can suppress the warning in this
|
||||||
|
* relatively likely and uninteresting case: we don't particularly
|
||||||
|
* care whether this is happening as a result of ENOENT or EACCES
|
||||||
|
* or any other reason. */
|
||||||
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
|
||||||
|
_("Unable to open path \"%s\": %s"),
|
||||||
|
path, g_strerror (saved_errno));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fstat (o_path_fd, &st) != 0)
|
if (fstat (o_path_fd, &st) != 0)
|
||||||
{
|
return glnx_throw (error,
|
||||||
g_debug ("Unable to get file type of %s: %s", path, g_strerror (errno));
|
_("Unable to get file type of \"%s\": %s"),
|
||||||
return FALSE;
|
path, g_strerror (errno));
|
||||||
}
|
|
||||||
|
|
||||||
/* Don't expose weird things */
|
/* Don't expose weird things */
|
||||||
if (!(S_ISDIR (st.st_mode) ||
|
if (!(S_ISDIR (st.st_mode) ||
|
||||||
S_ISREG (st.st_mode) ||
|
S_ISREG (st.st_mode) ||
|
||||||
S_ISLNK (st.st_mode) ||
|
S_ISLNK (st.st_mode) ||
|
||||||
S_ISSOCK (st.st_mode)))
|
S_ISSOCK (st.st_mode)))
|
||||||
{
|
return glnx_throw (error,
|
||||||
g_debug ("%s has unsupported file type 0o%o", path, st.st_mode & S_IFMT);
|
_("File \"%s\" has unsupported type 0o%o"),
|
||||||
return FALSE;
|
path, st.st_mode & S_IFMT);
|
||||||
}
|
|
||||||
|
|
||||||
/* O_PATH + fstatfs is the magic that we need to statfs without automounting the target */
|
/* O_PATH + fstatfs is the magic that we need to statfs without automounting the target */
|
||||||
if (fstatfs (o_path_fd, &stfs) != 0)
|
if (fstatfs (o_path_fd, &stfs) != 0)
|
||||||
{
|
return glnx_throw (error,
|
||||||
g_debug ("Unable to get filesystem information for %s: %s",
|
_("Unable to get filesystem information for \"%s\": %s"),
|
||||||
path, g_strerror (errno));
|
path, g_strerror (errno));
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stfs.f_type == AUTOFS_SUPER_MAGIC ||
|
if (stfs.f_type == AUTOFS_SUPER_MAGIC ||
|
||||||
(G_UNLIKELY (exports->test_flags & FLATPAK_EXPORTS_TEST_FLAGS_AUTOFS) &&
|
(G_UNLIKELY (exports->test_flags & FLATPAK_EXPORTS_TEST_FLAGS_AUTOFS) &&
|
||||||
@@ -939,7 +951,8 @@ _exports_path_expose (FlatpakExports *exports,
|
|||||||
{
|
{
|
||||||
if (!check_if_autofs_works (exports, path))
|
if (!check_if_autofs_works (exports, path))
|
||||||
{
|
{
|
||||||
g_debug ("ignoring blocking autofs path %s", path);
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK,
|
||||||
|
_("Ignoring blocking autofs path \"%s\""), path);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -954,17 +967,22 @@ _exports_path_expose (FlatpakExports *exports,
|
|||||||
create the parents for them anyway */
|
create the parents for them anyway */
|
||||||
if (flatpak_has_path_prefix (path, dont_export_in[i]))
|
if (flatpak_has_path_prefix (path, dont_export_in[i]))
|
||||||
{
|
{
|
||||||
g_debug ("skipping export for path %s in unsupported prefix", path);
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_MOUNTABLE_FILE,
|
||||||
|
_("Path \"%s\" is reserved by Flatpak"),
|
||||||
|
dont_export_in[i]);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; flatpak_abs_usrmerged_dirs[i] != NULL; i++)
|
for (i = 0; flatpak_abs_usrmerged_dirs[i] != NULL; i++)
|
||||||
{
|
{
|
||||||
/* Same as /usr, but for the directories that get merged into /usr */
|
/* Same as /usr, but for the directories that get merged into /usr.
|
||||||
|
* Keep the translatable string here the same as the one above */
|
||||||
if (flatpak_has_path_prefix (path, flatpak_abs_usrmerged_dirs[i]))
|
if (flatpak_has_path_prefix (path, flatpak_abs_usrmerged_dirs[i]))
|
||||||
{
|
{
|
||||||
g_debug ("skipping export for path %s in a /usr-merged directory", path);
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_MOUNTABLE_FILE,
|
||||||
|
_("Path \"%s\" is reserved by Flatpak"),
|
||||||
|
flatpak_abs_usrmerged_dirs[i]);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -988,8 +1006,8 @@ _exports_path_expose (FlatpakExports *exports,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) local_error = NULL;
|
||||||
g_autofree char *resolved = flatpak_exports_resolve_link_in_host (exports, path, &error);
|
g_autofree char *resolved = flatpak_exports_resolve_link_in_host (exports, path, &local_error);
|
||||||
g_autofree char *new_target = NULL;
|
g_autofree char *new_target = NULL;
|
||||||
|
|
||||||
if (resolved)
|
if (resolved)
|
||||||
@@ -1003,7 +1021,7 @@ _exports_path_expose (FlatpakExports *exports,
|
|||||||
|
|
||||||
flatpak_debug2 ("Trying to export the target instead: %s", new_target);
|
flatpak_debug2 ("Trying to export the target instead: %s", new_target);
|
||||||
|
|
||||||
if (_exports_path_expose (exports, mode, new_target, level + 1))
|
if (_exports_path_expose (exports, mode, new_target, level + 1, &local_error))
|
||||||
{
|
{
|
||||||
do_export_path (exports, path, FAKE_MODE_SYMLINK);
|
do_export_path (exports, path, FAKE_MODE_SYMLINK);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@@ -1011,12 +1029,14 @@ _exports_path_expose (FlatpakExports *exports,
|
|||||||
|
|
||||||
flatpak_debug2 ("Could not export target %s, so ignoring %s",
|
flatpak_debug2 ("Could not export target %s, so ignoring %s",
|
||||||
new_target, path);
|
new_target, path);
|
||||||
|
g_propagate_error (error, g_steal_pointer (&local_error));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
flatpak_debug2 ("%s is a symlink but we were unable to resolve it: %s",
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
|
||||||
path, error->message);
|
_("Unable to resolve symbolic link \"%s\": %s"),
|
||||||
|
path, local_error->message);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1035,16 +1055,25 @@ flatpak_exports_add_path_expose (FlatpakExports *exports,
|
|||||||
FlatpakFilesystemMode mode,
|
FlatpakFilesystemMode mode,
|
||||||
const char *path)
|
const char *path)
|
||||||
{
|
{
|
||||||
|
g_autoptr(GError) local_error = NULL;
|
||||||
|
|
||||||
g_return_if_fail (mode > FLATPAK_FILESYSTEM_MODE_NONE);
|
g_return_if_fail (mode > FLATPAK_FILESYSTEM_MODE_NONE);
|
||||||
g_return_if_fail (mode <= FLATPAK_FILESYSTEM_MODE_LAST);
|
g_return_if_fail (mode <= FLATPAK_FILESYSTEM_MODE_LAST);
|
||||||
_exports_path_expose (exports, mode, path, 0);
|
|
||||||
|
if (!_exports_path_expose (exports, mode, path, 0, &local_error))
|
||||||
|
g_debug ("Unable to %s: \"%s\": %s",
|
||||||
|
export_mode_to_verb (mode), path, local_error->message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
flatpak_exports_add_path_tmpfs (FlatpakExports *exports,
|
flatpak_exports_add_path_tmpfs (FlatpakExports *exports,
|
||||||
const char *path)
|
const char *path)
|
||||||
{
|
{
|
||||||
_exports_path_expose (exports, FAKE_MODE_TMPFS, path, 0);
|
g_autoptr(GError) local_error = NULL;
|
||||||
|
|
||||||
|
if (!_exports_path_expose (exports, FAKE_MODE_TMPFS, path, 0, &local_error))
|
||||||
|
g_debug ("Unable to %s: \"%s\": %s",
|
||||||
|
export_mode_to_verb (FAKE_MODE_TMPFS), path, local_error->message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -1065,7 +1094,11 @@ void
|
|||||||
flatpak_exports_add_path_dir (FlatpakExports *exports,
|
flatpak_exports_add_path_dir (FlatpakExports *exports,
|
||||||
const char *path)
|
const char *path)
|
||||||
{
|
{
|
||||||
_exports_path_expose (exports, FAKE_MODE_DIR, path, 0);
|
g_autoptr(GError) local_error = NULL;
|
||||||
|
|
||||||
|
if (!_exports_path_expose (exports, FAKE_MODE_DIR, path, 0, &local_error))
|
||||||
|
g_debug ("Unable to %s: \"%s\": %s",
|
||||||
|
export_mode_to_verb (FAKE_MODE_DIR), path, local_error->message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
Reference in New Issue
Block a user