import CS git flatpak-1.12.9-4.el8_10
This commit is contained in:
parent
e9a45618bd
commit
1e0192aaea
@ -0,0 +1,61 @@
|
||||
From fbe7a80a9e49ed364af2d7caf5902e3088f54587 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Wick <sebastian.wick@redhat.com>
|
||||
Date: Fri, 6 Feb 2026 17:56:21 +0100
|
||||
Subject: [PATCH] flatpak-bwrap: Add dup-ing variant
|
||||
flatpak_bwrap_add_args_data_fd_dup
|
||||
|
||||
---
|
||||
common/flatpak-bwrap-private.h | 5 +++++
|
||||
common/flatpak-bwrap.c | 20 ++++++++++++++++++++
|
||||
2 files changed, 25 insertions(+)
|
||||
|
||||
diff --git a/common/flatpak-bwrap-private.h b/common/flatpak-bwrap-private.h
|
||||
index 207d23a0..64bd26b6 100644
|
||||
--- a/common/flatpak-bwrap-private.h
|
||||
+++ b/common/flatpak-bwrap-private.h
|
||||
@@ -62,6 +62,11 @@ void flatpak_bwrap_append_bwrap (FlatpakBwrap *bwrap,
|
||||
FlatpakBwrap *other); /* Steals the fds */
|
||||
void flatpak_bwrap_append_args (FlatpakBwrap *bwrap,
|
||||
GPtrArray *other_array);
|
||||
+gboolean flatpak_bwrap_add_args_data_fd_dup (FlatpakBwrap *bwrap,
|
||||
+ const char *op,
|
||||
+ int fd,
|
||||
+ const char *path_optional,
|
||||
+ GError **error);
|
||||
void flatpak_bwrap_add_args_data_fd (FlatpakBwrap *bwrap,
|
||||
const char *op,
|
||||
int fd,
|
||||
diff --git a/common/flatpak-bwrap.c b/common/flatpak-bwrap.c
|
||||
index cda0dbfb..1694ffd4 100644
|
||||
--- a/common/flatpak-bwrap.c
|
||||
+++ b/common/flatpak-bwrap.c
|
||||
@@ -141,6 +141,26 @@ flatpak_bwrap_add_fd (FlatpakBwrap *bwrap,
|
||||
g_array_append_val (bwrap->fds, fd);
|
||||
}
|
||||
|
||||
+gboolean
|
||||
+flatpak_bwrap_add_args_data_fd_dup (FlatpakBwrap *bwrap,
|
||||
+ const char *op,
|
||||
+ int fd,
|
||||
+ const char *path_optional,
|
||||
+ GError **error)
|
||||
+{
|
||||
+ glnx_autofd int fd_dup = -1;
|
||||
+
|
||||
+ fd_dup = fcntl (fd, F_DUPFD_CLOEXEC, 3);
|
||||
+ if (fd_dup < 0)
|
||||
+ return glnx_throw_errno_prefix (error, "Failed to dup fd %d", fd);
|
||||
+
|
||||
+ flatpak_bwrap_add_args_data_fd (bwrap,
|
||||
+ op,
|
||||
+ g_steal_fd (&fd_dup),
|
||||
+ path_optional);
|
||||
+ return TRUE;
|
||||
+}
|
||||
+
|
||||
void
|
||||
flatpak_bwrap_add_arg_printf (FlatpakBwrap *bwrap, const char *format, ...)
|
||||
{
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
From 5096a974bcba5dfeddaea197b2ac63f558100858 Mon Sep 17 00:00:00 2001
|
||||
From: Simon McVittie <smcv@collabora.com>
|
||||
Date: Wed, 8 Apr 2026 09:44:55 +0100
|
||||
Subject: [PATCH] run: Mount original app on /run/parent/app when using
|
||||
--app-path=""
|
||||
|
||||
Before addressing CVE-2026-34078, we would always mount the original app
|
||||
*somewhere*, either /app (in the normal case) or /run/parent/app (when
|
||||
using a custom or empty /app for the subsandbox). The empty-app case
|
||||
regressed during the fix for CVE-2026-34078; bring back previous behaviour.
|
||||
|
||||
Fixes: ac62ebe3 "run: Use O_PATH fds for the runtime and app deploy directories"
|
||||
Resolves: https://github.com/flatpak/flatpak/issues/6568
|
||||
Signed-off-by: Simon McVittie <smcv@collabora.com>
|
||||
(cherry picked from commit fde4716f67b6620da57fd74481694eb58795d589)
|
||||
---
|
||||
common/flatpak-run.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/common/flatpak-run.c b/common/flatpak-run.c
|
||||
index 4ffc5fa3..a80d0050 100644
|
||||
--- a/common/flatpak-run.c
|
||||
+++ b/common/flatpak-run.c
|
||||
@@ -4476,6 +4476,7 @@ flatpak_run_app (FlatpakDecomposed *app_ref,
|
||||
}
|
||||
else if (custom_app_fd == FLATPAK_RUN_APP_DEPLOY_APP_EMPTY)
|
||||
{
|
||||
+ original_app_target_path = "/run/parent/app";
|
||||
app_fd = -1;
|
||||
app_files = NULL;
|
||||
}
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
From d05aeb399ba56e46ab3b7b4eed3669ab98a0df56 Mon Sep 17 00:00:00 2001
|
||||
From: Alberto Garcia <berto@igalia.com>
|
||||
Date: Wed, 8 Apr 2026 19:28:32 +0200
|
||||
Subject: [PATCH] portal: update max_fd after creating the instance ID pipe
|
||||
|
||||
fd_map_remap_fd() is called several times after this, and without this
|
||||
change it can allocate a target fd that collides with instance_id_fd.
|
||||
|
||||
Only the write end of the pipe needs to be considered because that's
|
||||
the one passed to the child.
|
||||
|
||||
Closes: https://github.com/flatpak/flatpak/issues/6570
|
||||
---
|
||||
portal/flatpak-portal.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/portal/flatpak-portal.c b/portal/flatpak-portal.c
|
||||
index a4378f77..3110071c 100644
|
||||
--- a/portal/flatpak-portal.c
|
||||
+++ b/portal/flatpak-portal.c
|
||||
@@ -1075,6 +1075,7 @@ handle_spawn (PortalFlatpak *object,
|
||||
|
||||
g_ptr_array_add (flatpak_argv, g_strdup_printf ("--instance-id-fd=%d", pipe_fds[1]));
|
||||
child_setup_data.instance_id_fd = pipe_fds[1];
|
||||
+ max_fd = MAX(max_fd, pipe_fds[1]);
|
||||
}
|
||||
|
||||
if (devel)
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,122 @@
|
||||
From 559c415b517c2533cf6b7294fb3f4cf99ed8e2ae Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Wick <sebastian.wick@redhat.com>
|
||||
Date: Wed, 8 Apr 2026 17:47:48 +0200
|
||||
Subject: [PATCH] run: Fix fd tracking in flatpak_run_add_app_info_args
|
||||
|
||||
Calls to flatpak_bwrap_add_args_data_fd take ownership over the fd they
|
||||
take. Closing them while they are still in the bwrap struct will abort
|
||||
later when the bwrap struct gets freed and it tries to close the already
|
||||
closed fd.
|
||||
|
||||
Fix this by using glnx_autofd and g_steal_fd.
|
||||
---
|
||||
common/flatpak-run.c | 34 +++++++++++++++++-----------------
|
||||
1 file changed, 17 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/common/flatpak-run.c b/common/flatpak-run.c
|
||||
index a80d0050..a11e26d6 100644
|
||||
--- a/common/flatpak-run.c
|
||||
+++ b/common/flatpak-run.c
|
||||
@@ -2602,13 +2602,17 @@ flatpak_run_add_app_info_args (FlatpakBwrap *bwrap,
|
||||
gboolean build,
|
||||
gboolean devel,
|
||||
char **app_info_path_out,
|
||||
- int instance_id_fd,
|
||||
+ int instance_id_fd_arg,
|
||||
char **instance_id_host_dir_out,
|
||||
GError **error)
|
||||
{
|
||||
g_autofree char *info_path = NULL;
|
||||
g_autofree char *bwrapinfo_path = NULL;
|
||||
- int fd, fd2, fd3;
|
||||
+ glnx_autofd int fd1 = -1;
|
||||
+ glnx_autofd int fd2 = -1;
|
||||
+ glnx_autofd int fd3 = -1;
|
||||
+ int info_fd;
|
||||
+ glnx_autofd int instance_id_fd = instance_id_fd_arg;
|
||||
g_autoptr(GKeyFile) keyfile = NULL;
|
||||
g_autofree char *runtime_path = NULL;
|
||||
const char *group;
|
||||
@@ -2754,8 +2758,8 @@ flatpak_run_add_app_info_args (FlatpakBwrap *bwrap,
|
||||
This way even if the bind-mount is unmounted we can find the real data.
|
||||
*/
|
||||
|
||||
- fd = open (info_path, O_RDONLY);
|
||||
- if (fd == -1)
|
||||
+ fd1 = info_fd = open (info_path, O_RDONLY);
|
||||
+ if (fd1 == -1)
|
||||
{
|
||||
int errsv = errno;
|
||||
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
|
||||
@@ -2766,7 +2770,6 @@ flatpak_run_add_app_info_args (FlatpakBwrap *bwrap,
|
||||
fd2 = open (info_path, O_RDONLY);
|
||||
if (fd2 == -1)
|
||||
{
|
||||
- close (fd);
|
||||
int errsv = errno;
|
||||
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
|
||||
_("Failed to open flatpak-info file: %s"), g_strerror (errsv));
|
||||
@@ -2774,9 +2777,9 @@ flatpak_run_add_app_info_args (FlatpakBwrap *bwrap,
|
||||
}
|
||||
|
||||
flatpak_bwrap_add_args_data_fd (bwrap,
|
||||
- "--file", fd, "/.flatpak-info");
|
||||
+ "--file", g_steal_fd (&fd1), "/.flatpak-info");
|
||||
flatpak_bwrap_add_args_data_fd (bwrap,
|
||||
- "--ro-bind-data", fd2, "/.flatpak-info");
|
||||
+ "--ro-bind-data", g_steal_fd (&fd2), "/.flatpak-info");
|
||||
|
||||
/* Tell the application that it's running under Flatpak in a generic way. */
|
||||
flatpak_bwrap_add_args (bwrap,
|
||||
@@ -2793,8 +2796,6 @@ flatpak_run_add_app_info_args (FlatpakBwrap *bwrap,
|
||||
fd3 = open (bwrapinfo_path, O_RDWR | O_CREAT, 0644);
|
||||
if (fd3 == -1)
|
||||
{
|
||||
- close (fd);
|
||||
- close (fd2);
|
||||
int errsv = errno;
|
||||
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
|
||||
_("Failed to open bwrapinfo.json file: %s"), g_strerror (errsv));
|
||||
@@ -2817,10 +2818,6 @@ flatpak_run_add_app_info_args (FlatpakBwrap *bwrap,
|
||||
if (errsv == EINTR)
|
||||
continue;
|
||||
|
||||
- close (fd);
|
||||
- close (fd2);
|
||||
- close (fd3);
|
||||
-
|
||||
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
|
||||
_("Failed to write to instance id fd: %s"), g_strerror (errsv));
|
||||
return FALSE;
|
||||
@@ -2830,13 +2827,14 @@ flatpak_run_add_app_info_args (FlatpakBwrap *bwrap,
|
||||
instance_id_size -= bytes_written;
|
||||
}
|
||||
|
||||
- close (instance_id_fd);
|
||||
+ /* explicitly close this as soon as we're done to notify the other side */
|
||||
+ g_clear_fd (&instance_id_fd, NULL);
|
||||
}
|
||||
|
||||
- flatpak_bwrap_add_args_data_fd (bwrap, "--info-fd", fd3, NULL);
|
||||
+ flatpak_bwrap_add_args_data_fd (bwrap, "--info-fd", g_steal_fd (&fd3), NULL);
|
||||
|
||||
if (app_info_path_out != NULL)
|
||||
- *app_info_path_out = g_strdup_printf ("/proc/self/fd/%d", fd);
|
||||
+ *app_info_path_out = g_strdup_printf ("/proc/self/fd/%d", info_fd);
|
||||
|
||||
if (instance_id_host_dir_out != NULL)
|
||||
*instance_id_host_dir_out = g_steal_pointer (&instance_id_host_dir);
|
||||
@@ -4697,7 +4695,9 @@ flatpak_run_app (FlatpakDecomposed *app_ref,
|
||||
app_id, flatpak_decomposed_get_branch (app_ref),
|
||||
runtime_ref, app_id_dir, app_context, extra_context,
|
||||
sandboxed, FALSE, flags & FLATPAK_RUN_FLAG_DEVEL,
|
||||
- &app_info_path, instance_id_fd, &instance_id_host_dir,
|
||||
+ &app_info_path,
|
||||
+ g_steal_fd (&instance_id_fd),
|
||||
+ &instance_id_host_dir,
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,28 @@
|
||||
From 9462b0f980aa0718a41601aaa87125f545c424eb Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Wick <sebastian.wick@redhat.com>
|
||||
Date: Wed, 8 Apr 2026 18:15:42 +0200
|
||||
Subject: [PATCH] utils: Improve error message when passing an FD numer which
|
||||
is not a FD
|
||||
|
||||
---
|
||||
common/flatpak-utils.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/common/flatpak-utils.c b/common/flatpak-utils.c
|
||||
index c2015941..938d8131 100644
|
||||
--- a/common/flatpak-utils.c
|
||||
+++ b/common/flatpak-utils.c
|
||||
@@ -9205,8 +9205,8 @@ flatpak_parse_fd (const char *fd_string,
|
||||
|
||||
fd = (int) parsed;
|
||||
|
||||
- if (!glnx_fstat (fd, &stbuf, error))
|
||||
- return -1;
|
||||
+ if (!glnx_fstat (fd, &stbuf, NULL))
|
||||
+ return glnx_fd_throw (error, "Not an open file descriptor: %d", fd);
|
||||
|
||||
return fd;
|
||||
}
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
From 9e145899fe0a28ce79d905b5efabc253b5c8050b Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Wick <sebastian.wick@redhat.com>
|
||||
Date: Wed, 8 Apr 2026 18:14:19 +0200
|
||||
Subject: [PATCH] run: Do not close --bind/--ro-bind
|
||||
|
||||
---
|
||||
app/flatpak-builtins-run.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/app/flatpak-builtins-run.c b/app/flatpak-builtins-run.c
|
||||
index 7edd7326..701e3454 100644
|
||||
--- a/app/flatpak-builtins-run.c
|
||||
+++ b/app/flatpak-builtins-run.c
|
||||
@@ -82,6 +82,7 @@ option_bind_fd_cb (const char *option_name,
|
||||
return glnx_throw (error, "File descriptors 0, 1, 2 are reserved");
|
||||
|
||||
g_array_append_val (opt_bind_fds, fd);
|
||||
+ fd = -1; /* ownership transferred to GArray */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -101,6 +102,7 @@ option_ro_bind_fd_cb (const char *option_name,
|
||||
return glnx_throw (error, "File descriptors 0, 1, 2 are reserved");
|
||||
|
||||
g_array_append_val (opt_ro_bind_fds, fd);
|
||||
+ fd = -1; /* ownership transferred to GArray */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,95 @@
|
||||
From 8708ab052d884cc84e6e71ea012e8d11eba41982 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Wick <sebastian.wick@redhat.com>
|
||||
Date: Wed, 8 Apr 2026 18:19:20 +0200
|
||||
Subject: [PATCH] run: Use the same FD validation for all FD options
|
||||
|
||||
---
|
||||
app/flatpak-builtins-run.c | 63 ++++++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 60 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/app/flatpak-builtins-run.c b/app/flatpak-builtins-run.c
|
||||
index 701e3454..d97dc0bf 100644
|
||||
--- a/app/flatpak-builtins-run.c
|
||||
+++ b/app/flatpak-builtins-run.c
|
||||
@@ -106,6 +106,63 @@ option_ro_bind_fd_cb (const char *option_name,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
+static gboolean
|
||||
+opt_instance_id_fd_cb (const char *option_name,
|
||||
+ const char *value,
|
||||
+ gpointer data,
|
||||
+ GError **error)
|
||||
+{
|
||||
+ glnx_autofd int fd = -1;
|
||||
+
|
||||
+ fd = flatpak_parse_fd (value, error);
|
||||
+ if (fd < 0)
|
||||
+ return FALSE;
|
||||
+
|
||||
+ if (fd < 3)
|
||||
+ return glnx_throw (error, "File descriptors 0, 1, 2 are reserved");
|
||||
+
|
||||
+ opt_instance_id_fd = g_steal_fd (&fd);
|
||||
+ return TRUE;
|
||||
+}
|
||||
+
|
||||
+static gboolean
|
||||
+opt_app_fd_cb (const char *option_name,
|
||||
+ const char *value,
|
||||
+ gpointer data,
|
||||
+ GError **error)
|
||||
+{
|
||||
+ glnx_autofd int fd = -1;
|
||||
+
|
||||
+ fd = flatpak_parse_fd (value, error);
|
||||
+ if (fd < 0)
|
||||
+ return FALSE;
|
||||
+
|
||||
+ if (fd < 3)
|
||||
+ return glnx_throw (error, "File descriptors 0, 1, 2 are reserved");
|
||||
+
|
||||
+ opt_app_fd = g_steal_fd (&fd);
|
||||
+ return TRUE;
|
||||
+}
|
||||
+
|
||||
+static gboolean
|
||||
+opt_usr_fd_cb (const char *option_name,
|
||||
+ const char *value,
|
||||
+ gpointer data,
|
||||
+ GError **error)
|
||||
+{
|
||||
+ glnx_autofd int fd = -1;
|
||||
+
|
||||
+ fd = flatpak_parse_fd (value, error);
|
||||
+ if (fd < 0)
|
||||
+ return FALSE;
|
||||
+
|
||||
+ if (fd < 3)
|
||||
+ return glnx_throw (error, "File descriptors 0, 1, 2 are reserved");
|
||||
+
|
||||
+ opt_usr_fd = g_steal_fd (&fd);
|
||||
+ return TRUE;
|
||||
+}
|
||||
+
|
||||
static GOptionEntry options[] = {
|
||||
{ "arch", 0, 0, G_OPTION_ARG_STRING, &opt_arch, N_("Arch to use"), N_("ARCH") },
|
||||
{ "command", 0, 0, G_OPTION_ARG_STRING, &opt_command, N_("Command to run"), N_("COMMAND") },
|
||||
@@ -130,11 +187,11 @@ static GOptionEntry options[] = {
|
||||
{ "parent-pid", 0, 0, G_OPTION_ARG_INT, &opt_parent_pid, N_("Use PID as parent pid for sharing namespaces"), N_("PID") },
|
||||
{ "parent-expose-pids", 0, 0, G_OPTION_ARG_NONE, &opt_parent_expose_pids, N_("Make processes visible in parent namespace"), NULL },
|
||||
{ "parent-share-pids", 0, 0, G_OPTION_ARG_NONE, &opt_parent_share_pids, N_("Share process ID namespace with parent"), NULL },
|
||||
- { "instance-id-fd", 0, 0, G_OPTION_ARG_INT, &opt_instance_id_fd, N_("Write the instance ID to the given file descriptor"), NULL },
|
||||
+ { "instance-id-fd", 0, 0, G_OPTION_ARG_CALLBACK, &opt_instance_id_fd_cb, N_("Write the instance ID to the given file descriptor"), NULL },
|
||||
{ "app-path", 0, 0, G_OPTION_ARG_FILENAME, &opt_app_path, N_("Use PATH instead of the app's /app"), N_("PATH") },
|
||||
- { "app-fd", 0, 0, G_OPTION_ARG_INT, &opt_app_fd, N_("Use FD instead of the app's /app"), N_("FD") },
|
||||
+ { "app-fd", 0, 0, G_OPTION_ARG_CALLBACK, &opt_app_fd_cb, N_("Use FD instead of the app's /app"), N_("FD") },
|
||||
{ "usr-path", 0, 0, G_OPTION_ARG_FILENAME, &opt_usr_path, N_("Use PATH instead of the runtime's /usr"), N_("PATH") },
|
||||
- { "usr-fd", 0, 0, G_OPTION_ARG_INT, &opt_usr_fd, N_("Use FD instead of the runtime's /usr"), N_("FD") },
|
||||
+ { "usr-fd", 0, 0, G_OPTION_ARG_INT, &opt_usr_fd_cb, N_("Use FD instead of the runtime's /usr"), N_("FD") },
|
||||
{ "bind-fd", 0, 0, G_OPTION_ARG_CALLBACK | G_OPTION_FLAG_HIDDEN, &option_bind_fd_cb, N_("Bind mount the file or directory referred to by FD to its canonicalized path"), N_("FD") },
|
||||
{ "ro-bind-fd", 0, 0, G_OPTION_ARG_CALLBACK | G_OPTION_FLAG_HIDDEN, &option_ro_bind_fd_cb, N_("Bind mount the file or directory referred to by FD read-only to its canonicalized path"), N_("FD") },
|
||||
{ NULL }
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,101 @@
|
||||
From 3469414dbb068f770b594e6a3f47cd143aff6172 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Wick <sebastian.wick@redhat.com>
|
||||
Date: Wed, 8 Apr 2026 21:59:19 +0200
|
||||
Subject: [PATCH] run: Add bind-fd and ro-bind-fd binds after all other binds
|
||||
|
||||
This is only moving it a bit down because
|
||||
flatpak_run_add_environment_args still adds a whole bunch of binds which
|
||||
then can over-mount the user requested binds (bind-fd, ro-bind-fd).
|
||||
---
|
||||
common/flatpak-run.c | 68 ++++++++++++++++++++++----------------------
|
||||
1 file changed, 34 insertions(+), 34 deletions(-)
|
||||
|
||||
diff --git a/common/flatpak-run.c b/common/flatpak-run.c
|
||||
index a11e26d6..58b96dc1 100644
|
||||
--- a/common/flatpak-run.c
|
||||
+++ b/common/flatpak-run.c
|
||||
@@ -4720,40 +4720,6 @@ flatpak_run_app (FlatpakDecomposed *app_ref,
|
||||
flatpak_bwrap_add_arg_printf (bwrap, "/run/user/%d", getuid ());
|
||||
}
|
||||
|
||||
- for (i = 0; bind_fds && i < bind_fds->len; i++)
|
||||
- {
|
||||
- int fd = g_array_index (bind_fds, int, i);
|
||||
- g_autofree char *path = NULL;
|
||||
-
|
||||
- /* We get the path the fd refers to, to determine to mount point
|
||||
- * destination inside the sandbox */
|
||||
- path = get_path_for_fd (fd, error);
|
||||
- if (!path)
|
||||
- return FALSE;
|
||||
-
|
||||
- if (!flatpak_bwrap_add_args_data_fd_dup (bwrap,
|
||||
- "--bind-fd", fd, path,
|
||||
- error))
|
||||
- return FALSE;
|
||||
- }
|
||||
-
|
||||
- for (i = 0; ro_bind_fds && i < ro_bind_fds->len; i++)
|
||||
- {
|
||||
- int fd = g_array_index (ro_bind_fds, int, i);
|
||||
- g_autofree char *path = NULL;
|
||||
-
|
||||
- /* We get the path the fd refers to, to determine to mount point
|
||||
- * destination inside the sandbox */
|
||||
- path = get_path_for_fd (fd, error);
|
||||
- if (!path)
|
||||
- return FALSE;
|
||||
-
|
||||
- if (!flatpak_bwrap_add_args_data_fd_dup (bwrap,
|
||||
- "--ro-bind-fd", fd, path,
|
||||
- error))
|
||||
- return FALSE;
|
||||
- }
|
||||
-
|
||||
if (!flatpak_run_add_dconf_args (bwrap, app_id, metakey, error))
|
||||
return FALSE;
|
||||
|
||||
@@ -4789,6 +4755,40 @@ flatpak_run_app (FlatpakDecomposed *app_ref,
|
||||
"--symlink", "/usr/lib/debug/source", "/run/build-runtime",
|
||||
NULL);
|
||||
|
||||
+ for (i = 0; bind_fds && i < bind_fds->len; i++)
|
||||
+ {
|
||||
+ int fd = g_array_index (bind_fds, int, i);
|
||||
+ g_autofree char *path = NULL;
|
||||
+
|
||||
+ /* We get the path the fd refers to, to determine to mount point
|
||||
+ * destination inside the sandbox */
|
||||
+ path = get_path_for_fd (fd, error);
|
||||
+ if (!path)
|
||||
+ return FALSE;
|
||||
+
|
||||
+ if (!flatpak_bwrap_add_args_data_fd_dup (bwrap,
|
||||
+ "--bind-fd", fd, path,
|
||||
+ error))
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; ro_bind_fds && i < ro_bind_fds->len; i++)
|
||||
+ {
|
||||
+ int fd = g_array_index (ro_bind_fds, int, i);
|
||||
+ g_autofree char *path = NULL;
|
||||
+
|
||||
+ /* We get the path the fd refers to, to determine to mount point
|
||||
+ * destination inside the sandbox */
|
||||
+ path = get_path_for_fd (fd, error);
|
||||
+ if (!path)
|
||||
+ return FALSE;
|
||||
+
|
||||
+ if (!flatpak_bwrap_add_args_data_fd_dup (bwrap,
|
||||
+ "--ro-bind-fd", fd, path,
|
||||
+ error))
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
if (cwd)
|
||||
flatpak_bwrap_add_args (bwrap, "--chdir", cwd, NULL);
|
||||
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
From dd0a1c25299907b69085aae0fab32becbfca884e Mon Sep 17 00:00:00 2001
|
||||
From: Alberto Garcia <berto@igalia.com>
|
||||
Date: Wed, 8 Apr 2026 19:44:29 +0200
|
||||
Subject: [PATCH] portal: use g_array_index() to read from expose_fds /
|
||||
expose_fds_ro
|
||||
|
||||
The data field of a GArray is a gchar* but we're storing integers
|
||||
here, so use the proper method to ensure that we're getting the
|
||||
element at the right offset and with the correct type.
|
||||
---
|
||||
portal/flatpak-portal.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/portal/flatpak-portal.c b/portal/flatpak-portal.c
|
||||
index 3110071c..59a17b2b 100644
|
||||
--- a/portal/flatpak-portal.c
|
||||
+++ b/portal/flatpak-portal.c
|
||||
@@ -1219,7 +1219,7 @@ handle_spawn (PortalFlatpak *object,
|
||||
{
|
||||
int remapped_fd;
|
||||
|
||||
- remapped_fd = fd_map_remap_fd (fd_map, &max_fd, expose_fds->data[i]);
|
||||
+ remapped_fd = fd_map_remap_fd (fd_map, &max_fd, g_array_index (expose_fds, int, i));
|
||||
|
||||
g_ptr_array_add (flatpak_argv, g_strdup_printf ("--bind-fd=%d",
|
||||
remapped_fd));
|
||||
@@ -1229,7 +1229,7 @@ handle_spawn (PortalFlatpak *object,
|
||||
{
|
||||
int remapped_fd;
|
||||
|
||||
- remapped_fd = fd_map_remap_fd (fd_map, &max_fd, expose_fds_ro->data[i]);
|
||||
+ remapped_fd = fd_map_remap_fd (fd_map, &max_fd, g_array_index (expose_fds_ro, int, i));
|
||||
|
||||
g_ptr_array_add (flatpak_argv, g_strdup_printf ("--ro-bind-fd=%d",
|
||||
remapped_fd));
|
||||
--
|
||||
2.54.0
|
||||
|
||||
28
SOURCES/CVE-2026-34078-18-run-fix-backport-mistake.patch
Normal file
28
SOURCES/CVE-2026-34078-18-run-fix-backport-mistake.patch
Normal file
@ -0,0 +1,28 @@
|
||||
From 37a73712d0e5b20d31fd1a1bd4df1b66e53b32ee Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Wick <sebastian.wick@redhat.com>
|
||||
Date: Thu, 9 Apr 2026 00:56:40 +0200
|
||||
Subject: [PATCH] run: Fix backport mistake
|
||||
|
||||
Not even sure how this happened. Whoops. It's time to get some sleep.
|
||||
|
||||
Fixes: c89a0c50 ("run: Use the same FD validation for all FD options")
|
||||
---
|
||||
app/flatpak-builtins-run.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/app/flatpak-builtins-run.c b/app/flatpak-builtins-run.c
|
||||
index d97dc0bf..e174848e 100644
|
||||
--- a/app/flatpak-builtins-run.c
|
||||
+++ b/app/flatpak-builtins-run.c
|
||||
@@ -191,7 +191,7 @@ static GOptionEntry options[] = {
|
||||
{ "app-path", 0, 0, G_OPTION_ARG_FILENAME, &opt_app_path, N_("Use PATH instead of the app's /app"), N_("PATH") },
|
||||
{ "app-fd", 0, 0, G_OPTION_ARG_CALLBACK, &opt_app_fd_cb, N_("Use FD instead of the app's /app"), N_("FD") },
|
||||
{ "usr-path", 0, 0, G_OPTION_ARG_FILENAME, &opt_usr_path, N_("Use PATH instead of the runtime's /usr"), N_("PATH") },
|
||||
- { "usr-fd", 0, 0, G_OPTION_ARG_INT, &opt_usr_fd_cb, N_("Use FD instead of the runtime's /usr"), N_("FD") },
|
||||
+ { "usr-fd", 0, 0, G_OPTION_ARG_CALLBACK, &opt_usr_fd_cb, N_("Use FD instead of the runtime's /usr"), N_("FD") },
|
||||
{ "bind-fd", 0, 0, G_OPTION_ARG_CALLBACK | G_OPTION_FLAG_HIDDEN, &option_bind_fd_cb, N_("Bind mount the file or directory referred to by FD to its canonicalized path"), N_("FD") },
|
||||
{ "ro-bind-fd", 0, 0, G_OPTION_ARG_CALLBACK | G_OPTION_FLAG_HIDDEN, &option_ro_bind_fd_cb, N_("Bind mount the file or directory referred to by FD read-only to its canonicalized path"), N_("FD") },
|
||||
{ NULL }
|
||||
--
|
||||
2.54.0
|
||||
|
||||
100
SOURCES/CVE-2026-34078-19-run-cope-with-an-empty-runtime.patch
Normal file
100
SOURCES/CVE-2026-34078-19-run-cope-with-an-empty-runtime.patch
Normal file
@ -0,0 +1,100 @@
|
||||
From dc40c215b8678a5eabdb3b3ff8556d29c67f8fde Mon Sep 17 00:00:00 2001
|
||||
From: Simon McVittie <smcv@collabora.com>
|
||||
Date: Thu, 9 Apr 2026 18:45:04 +0100
|
||||
Subject: [PATCH] run: Cope with an empty runtime
|
||||
|
||||
When FlatpakDir runs extra-data helpers in apply_extra_data(),
|
||||
if the helper is statically linked, it might not need a runtime at all.
|
||||
For example the helper for openh264 falls into this category.
|
||||
|
||||
Fixes: ac62ebe3 "run: Use O_PATH fds for the runtime and app deploy directories"
|
||||
Helps: https://github.com/flatpak/flatpak/issues/6583
|
||||
Signed-off-by: Simon McVittie <smcv@collabora.com>
|
||||
(cherry picked from commit aa1a54c9dae25fd13ebc936e06996f8db39f4aa5)
|
||||
---
|
||||
common/flatpak-run.c | 30 +++++++++++++++++++++++++-----
|
||||
1 file changed, 25 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/common/flatpak-run.c b/common/flatpak-run.c
|
||||
index 58b96dc1..bd6536ac 100644
|
||||
--- a/common/flatpak-run.c
|
||||
+++ b/common/flatpak-run.c
|
||||
@@ -2842,6 +2842,10 @@ flatpak_run_add_app_info_args (FlatpakBwrap *bwrap,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * @runtime_fd: the /usr for the runtime, or -1 if running with no runtime,
|
||||
+ * perhaps to unpack extra-data
|
||||
+ */
|
||||
static void
|
||||
add_tzdata_args (FlatpakBwrap *bwrap,
|
||||
int runtime_fd)
|
||||
@@ -2853,14 +2857,19 @@ add_tzdata_args (FlatpakBwrap *bwrap,
|
||||
g_autofree char *runtime_zoneinfo = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
+ g_return_if_fail (runtime_fd >= -1);
|
||||
+
|
||||
raw_timezone = flatpak_get_timezone ();
|
||||
timezone_content = g_strdup_printf ("%s\n", raw_timezone);
|
||||
localtime_content = g_strconcat ("../usr/share/zoneinfo/", raw_timezone, NULL);
|
||||
|
||||
- zoneinfo_fd = glnx_chaseat (runtime_fd, "share/zoneinfo",
|
||||
- GLNX_CHASE_RESOLVE_BENEATH |
|
||||
- GLNX_CHASE_MUST_BE_DIRECTORY,
|
||||
- NULL);
|
||||
+ if (runtime_fd >= 0)
|
||||
+ {
|
||||
+ zoneinfo_fd = glnx_chaseat (runtime_fd, "share/zoneinfo",
|
||||
+ GLNX_CHASE_RESOLVE_BENEATH |
|
||||
+ GLNX_CHASE_MUST_BE_DIRECTORY,
|
||||
+ NULL);
|
||||
+ }
|
||||
|
||||
runtime_zoneinfo = g_strconcat ("share/zoneinfo/", raw_timezone, NULL);
|
||||
|
||||
@@ -3370,6 +3379,10 @@ setup_seccomp (FlatpakBwrap *bwrap,
|
||||
}
|
||||
#endif
|
||||
|
||||
+/*
|
||||
+ * @runtime_fd: the /usr for the runtime, or -1 if running with no runtime,
|
||||
+ * perhaps to unpack extra-data
|
||||
+ */
|
||||
static void
|
||||
flatpak_run_setup_usr_links (FlatpakBwrap *bwrap,
|
||||
int runtime_fd,
|
||||
@@ -3423,6 +3436,10 @@ flatpak_run_setup_usr_links (FlatpakBwrap *bwrap,
|
||||
}
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * @runtime_fd: the /usr for the runtime, or -1 if running with no runtime,
|
||||
+ * perhaps to unpack extra-data
|
||||
+ */
|
||||
gboolean
|
||||
flatpak_run_setup_base_argv (FlatpakBwrap *bwrap,
|
||||
int runtime_fd,
|
||||
@@ -3439,6 +3456,8 @@ flatpak_run_setup_base_argv (FlatpakBwrap *bwrap,
|
||||
gulong pers;
|
||||
gid_t gid = getgid ();
|
||||
|
||||
+ g_return_val_if_fail (runtime_fd >= -1, FALSE);
|
||||
+
|
||||
run_dir = g_strdup_printf ("/run/user/%d", getuid ());
|
||||
|
||||
passwd_contents = g_strdup_printf ("%s:x:%d:%d:%s:%s:%s\n"
|
||||
@@ -3512,7 +3531,8 @@ flatpak_run_setup_base_argv (FlatpakBwrap *bwrap,
|
||||
else if (g_file_test ("/var/lib/dbus/machine-id", G_FILE_TEST_EXISTS))
|
||||
flatpak_bwrap_add_args (bwrap, "--ro-bind", "/var/lib/dbus/machine-id", "/etc/machine-id", NULL);
|
||||
|
||||
- if ((flags & FLATPAK_RUN_FLAG_WRITABLE_ETC) == 0)
|
||||
+ if (runtime_fd >= 0
|
||||
+ && (flags & FLATPAK_RUN_FLAG_WRITABLE_ETC) == 0)
|
||||
{
|
||||
g_auto(GLnxDirFdIterator) dfd_iter = { 0, };
|
||||
struct dirent *dent;
|
||||
--
|
||||
2.54.0
|
||||
|
||||
94
SOURCES/CVE-2026-34078-2-utils-add-flatpak-parse-fd.patch
Normal file
94
SOURCES/CVE-2026-34078-2-utils-add-flatpak-parse-fd.patch
Normal file
@ -0,0 +1,94 @@
|
||||
From 8ce576a3b950d6ab735a5e049342d91b36685f94 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Wick <sebastian.wick@redhat.com>
|
||||
Date: Fri, 6 Feb 2026 17:14:49 +0100
|
||||
Subject: [PATCH] utils: Add flatpak_parse_fd
|
||||
|
||||
This is meant to parse file descriptor strings passed via the command
|
||||
line. It is not a security mechanism and will happily accept fds 0-3 as
|
||||
well.
|
||||
---
|
||||
common/flatpak-context.c | 19 +++++++------------
|
||||
common/flatpak-utils-private.h | 3 +++
|
||||
common/flatpak-utils.c | 22 ++++++++++++++++++++++
|
||||
3 files changed, 32 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/common/flatpak-context.c b/common/flatpak-context.c
|
||||
index 53b79807..992243e3 100644
|
||||
--- a/common/flatpak-context.c
|
||||
+++ b/common/flatpak-context.c
|
||||
@@ -1304,21 +1304,16 @@ option_env_fd_cb (const gchar *option_name,
|
||||
GError **error)
|
||||
{
|
||||
FlatpakContext *context = data;
|
||||
- guint64 fd;
|
||||
- gchar *endptr;
|
||||
- gboolean ret;
|
||||
+ glnx_autofd int fd = -1;
|
||||
|
||||
- fd = g_ascii_strtoull (value, &endptr, 10);
|
||||
-
|
||||
- if (endptr == NULL || *endptr != '\0' || fd > G_MAXINT)
|
||||
- return glnx_throw (error, "Not a valid file descriptor: %s", value);
|
||||
-
|
||||
- ret = flatpak_context_parse_env_fd (context, (int) fd, error);
|
||||
+ fd = flatpak_parse_fd (value, error);
|
||||
+ if (fd < 0)
|
||||
+ return FALSE;
|
||||
|
||||
- if (fd >= 3)
|
||||
- close (fd);
|
||||
+ if (fd < 3)
|
||||
+ return glnx_throw (error, "File descriptors 0, 1, 2 are reserved");
|
||||
|
||||
- return ret;
|
||||
+ return flatpak_context_parse_env_fd (context, fd, error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
diff --git a/common/flatpak-utils-private.h b/common/flatpak-utils-private.h
|
||||
index f79b22c8..754fe412 100644
|
||||
--- a/common/flatpak-utils-private.h
|
||||
+++ b/common/flatpak-utils-private.h
|
||||
@@ -927,6 +927,9 @@ void flatpak_print_escaped_string (const char *s,
|
||||
gboolean flatpak_validate_path_characters (const char *path,
|
||||
GError **error);
|
||||
|
||||
+int flatpak_parse_fd (const char *fd_string,
|
||||
+ GError **error);
|
||||
+
|
||||
#define FLATPAK_MESSAGE_ID "c7b39b1e006b464599465e105b361485"
|
||||
|
||||
#endif /* __FLATPAK_UTILS_H__ */
|
||||
diff --git a/common/flatpak-utils.c b/common/flatpak-utils.c
|
||||
index 0ab84064..c2015941 100644
|
||||
--- a/common/flatpak-utils.c
|
||||
+++ b/common/flatpak-utils.c
|
||||
@@ -9188,3 +9188,25 @@ flatpak_validate_path_characters (const char *path,
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
+
|
||||
+int
|
||||
+flatpak_parse_fd (const char *fd_string,
|
||||
+ GError **error)
|
||||
+{
|
||||
+ guint64 parsed;
|
||||
+ char *endptr;
|
||||
+ int fd;
|
||||
+ struct stat stbuf;
|
||||
+
|
||||
+ parsed = g_ascii_strtoull (fd_string, &endptr, 10);
|
||||
+
|
||||
+ if (endptr == NULL || *endptr != '\0' || parsed > G_MAXINT)
|
||||
+ return glnx_fd_throw (error, "Not a valid file descriptor: %s", fd_string);
|
||||
+
|
||||
+ fd = (int) parsed;
|
||||
+
|
||||
+ if (!glnx_fstat (fd, &stbuf, error))
|
||||
+ return -1;
|
||||
+
|
||||
+ return fd;
|
||||
+}
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,44 @@
|
||||
From 630fcba57765ac64a0cebc31257e63a5bc530961 Mon Sep 17 00:00:00 2001
|
||||
From: Simon McVittie <smcv@collabora.com>
|
||||
Date: Thu, 9 Apr 2026 18:47:40 +0100
|
||||
Subject: [PATCH] dir: In apply_extra_data(), don't assume there is always a
|
||||
runtime
|
||||
|
||||
org.freedesktop.Platform.openh264 is one example of an extension that
|
||||
runs a statically-linked extra-data helper, with no runtime. Only open
|
||||
the runtime if there is one.
|
||||
|
||||
Fixes: ac62ebe3 "run: Use O_PATH fds for the runtime and app deploy directories"
|
||||
Resolves: https://github.com/flatpak/flatpak/issues/6583
|
||||
Signed-off-by: Simon McVittie <smcv@collabora.com>
|
||||
(cherry picked from commit c14ad3722940706730a76997c6925f9998106f90)
|
||||
---
|
||||
common/flatpak-dir.c | 12 ++++++++----
|
||||
1 file changed, 8 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c
|
||||
index 94d2d4f2..adc9bf62 100644
|
||||
--- a/common/flatpak-dir.c
|
||||
+++ b/common/flatpak-dir.c
|
||||
@@ -8015,10 +8015,14 @@ apply_extra_data (FlatpakDir *self,
|
||||
NULL);
|
||||
|
||||
glnx_autofd int usr_fd = -1;
|
||||
- usr_fd = open (flatpak_file_get_path_cached (runtime_files),
|
||||
- O_PATH | O_CLOEXEC | O_NOFOLLOW);
|
||||
- if (usr_fd < 0)
|
||||
- return glnx_throw_errno_prefix (error, "Failed to open runtime files");
|
||||
+
|
||||
+ if (runtime_files != NULL)
|
||||
+ {
|
||||
+ usr_fd = open (flatpak_file_get_path_cached (runtime_files),
|
||||
+ O_PATH | O_CLOEXEC | O_NOFOLLOW);
|
||||
+ if (usr_fd < 0)
|
||||
+ return glnx_throw_errno_prefix (error, "Failed to open runtime files");
|
||||
+ }
|
||||
|
||||
if (!flatpak_run_setup_base_argv (bwrap, usr_fd, NULL, runtime_arch,
|
||||
/* Might need multiarch in apply_extra (see e.g. #3742). Should be pretty safe in this limited context */
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,52 @@
|
||||
From 0ac58a6734a3d5f6a0445cfe3310596e382c092b Mon Sep 17 00:00:00 2001
|
||||
From: Simon McVittie <smcv@collabora.com>
|
||||
Date: Fri, 10 Apr 2026 09:58:05 +0100
|
||||
Subject: [PATCH] utils: Add flatpak_set_cloexec()
|
||||
|
||||
Helps: https://github.com/flatpak/flatpak/issues/6582
|
||||
Signed-off-by: Simon McVittie <smcv@collabora.com>
|
||||
(cherry picked from commit 8a989c790d9121f53ada88fd001a3997b9e40632)
|
||||
---
|
||||
common/flatpak-utils-private.h | 2 ++
|
||||
common/flatpak-utils.c | 17 +++++++++++++++++
|
||||
2 files changed, 19 insertions(+)
|
||||
|
||||
diff --git a/common/flatpak-utils-private.h b/common/flatpak-utils-private.h
|
||||
index 754fe412..fd819c71 100644
|
||||
--- a/common/flatpak-utils-private.h
|
||||
+++ b/common/flatpak-utils-private.h
|
||||
@@ -932,4 +932,6 @@ int flatpak_parse_fd (const char *fd_string,
|
||||
|
||||
#define FLATPAK_MESSAGE_ID "c7b39b1e006b464599465e105b361485"
|
||||
|
||||
+gboolean flatpak_set_cloexec (int fd);
|
||||
+
|
||||
#endif /* __FLATPAK_UTILS_H__ */
|
||||
diff --git a/common/flatpak-utils.c b/common/flatpak-utils.c
|
||||
index 938d8131..446b3325 100644
|
||||
--- a/common/flatpak-utils.c
|
||||
+++ b/common/flatpak-utils.c
|
||||
@@ -9210,3 +9210,20 @@ flatpak_parse_fd (const char *fd_string,
|
||||
|
||||
return fd;
|
||||
}
|
||||
+
|
||||
+/* Sets errno on failure. */
|
||||
+gboolean
|
||||
+flatpak_set_cloexec (int fd)
|
||||
+{
|
||||
+ int flags = fcntl (fd, F_GETFD);
|
||||
+
|
||||
+ if (flags == -1)
|
||||
+ return FALSE;
|
||||
+
|
||||
+ flags |= FD_CLOEXEC;
|
||||
+
|
||||
+ if (fcntl (fd, F_SETFD, flags) < 0)
|
||||
+ return FALSE;
|
||||
+
|
||||
+ return TRUE;
|
||||
+}
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,102 @@
|
||||
From 5807aa3d7712d2fb5c294056dd90431cd863fded Mon Sep 17 00:00:00 2001
|
||||
From: Simon McVittie <smcv@collabora.com>
|
||||
Date: Fri, 10 Apr 2026 10:07:14 +0100
|
||||
Subject: [PATCH] run, context: Mark fd arguments as close-on-exec
|
||||
|
||||
On entry to `flatpak run`, these fds have been inheritable (not
|
||||
FD_CLOEXEC), otherwise they would not have been inherited; but we don't
|
||||
want the "payload" command to inherit them, so set them as
|
||||
non-close-on-exec as soon as we receive them. In the cases where we pass
|
||||
them down to the underlying bwrap command, we'll either dup them, or
|
||||
set them to be inheritable again (in practice we dup them).
|
||||
|
||||
In particular, Chromium-derived web browsers get very upset when their
|
||||
subsandbox processes inherit unexpected fds, which has been causing crashes
|
||||
with no useful diagnostic information since CVE-2026-34078 was fixed.
|
||||
|
||||
Fixes: 1b5e886d "run: Add --usr-fd and --app-fd options"
|
||||
Fixes: b5ae89ed "run: Add --(ro-)bind-fd options"
|
||||
Resolves: https://github.com/flatpak/flatpak/issues/6582
|
||||
Signed-off-by: Simon McVittie <smcv@collabora.com>
|
||||
(cherry picked from commit 0902090726c2e51b1c6f22c64d708a4895a196e7)
|
||||
---
|
||||
app/flatpak-builtins-run.c | 15 +++++++++++++++
|
||||
common/flatpak-context.c | 8 ++++++++
|
||||
2 files changed, 23 insertions(+)
|
||||
|
||||
diff --git a/app/flatpak-builtins-run.c b/app/flatpak-builtins-run.c
|
||||
index e174848e..cc69423e 100644
|
||||
--- a/app/flatpak-builtins-run.c
|
||||
+++ b/app/flatpak-builtins-run.c
|
||||
@@ -81,6 +81,9 @@ option_bind_fd_cb (const char *option_name,
|
||||
if (fd < 3)
|
||||
return glnx_throw (error, "File descriptors 0, 1, 2 are reserved");
|
||||
|
||||
+ if (!flatpak_set_cloexec (fd))
|
||||
+ return glnx_throw_errno_prefix (error, "--bind-fd");
|
||||
+
|
||||
g_array_append_val (opt_bind_fds, fd);
|
||||
fd = -1; /* ownership transferred to GArray */
|
||||
return TRUE;
|
||||
@@ -101,6 +104,9 @@ option_ro_bind_fd_cb (const char *option_name,
|
||||
if (fd < 3)
|
||||
return glnx_throw (error, "File descriptors 0, 1, 2 are reserved");
|
||||
|
||||
+ if (!flatpak_set_cloexec (fd))
|
||||
+ return glnx_throw_errno_prefix (error, "--ro-bind-fd");
|
||||
+
|
||||
g_array_append_val (opt_ro_bind_fds, fd);
|
||||
fd = -1; /* ownership transferred to GArray */
|
||||
return TRUE;
|
||||
@@ -121,6 +127,9 @@ opt_instance_id_fd_cb (const char *option_name,
|
||||
if (fd < 3)
|
||||
return glnx_throw (error, "File descriptors 0, 1, 2 are reserved");
|
||||
|
||||
+ if (!flatpak_set_cloexec (fd))
|
||||
+ return glnx_throw_errno_prefix (error, "--instance-id-fd");
|
||||
+
|
||||
opt_instance_id_fd = g_steal_fd (&fd);
|
||||
return TRUE;
|
||||
}
|
||||
@@ -140,6 +149,9 @@ opt_app_fd_cb (const char *option_name,
|
||||
if (fd < 3)
|
||||
return glnx_throw (error, "File descriptors 0, 1, 2 are reserved");
|
||||
|
||||
+ if (!flatpak_set_cloexec (fd))
|
||||
+ return glnx_throw_errno_prefix (error, "--app-fd");
|
||||
+
|
||||
opt_app_fd = g_steal_fd (&fd);
|
||||
return TRUE;
|
||||
}
|
||||
@@ -159,6 +171,9 @@ opt_usr_fd_cb (const char *option_name,
|
||||
if (fd < 3)
|
||||
return glnx_throw (error, "File descriptors 0, 1, 2 are reserved");
|
||||
|
||||
+ if (!flatpak_set_cloexec (fd))
|
||||
+ return glnx_throw_errno_prefix (error, "--usr-fd");
|
||||
+
|
||||
opt_usr_fd = g_steal_fd (&fd);
|
||||
return TRUE;
|
||||
}
|
||||
diff --git a/common/flatpak-context.c b/common/flatpak-context.c
|
||||
index 992243e3..3ff4ac16 100644
|
||||
--- a/common/flatpak-context.c
|
||||
+++ b/common/flatpak-context.c
|
||||
@@ -1313,6 +1313,14 @@ option_env_fd_cb (const gchar *option_name,
|
||||
if (fd < 3)
|
||||
return glnx_throw (error, "File descriptors 0, 1, 2 are reserved");
|
||||
|
||||
+ /* This is not strictly necessary, because we're going to close it after
|
||||
+ * parsing the environment block, but let's be consistent with other fd
|
||||
+ * arguments that we need to avoid being inherited by the "payload"
|
||||
+ * command. This is also a convenient place to validate that it's an
|
||||
+ * open fd. */
|
||||
+ if (!flatpak_set_cloexec (fd))
|
||||
+ return glnx_throw_errno_prefix (error, "--env-fd");
|
||||
+
|
||||
return flatpak_context_parse_env_fd (context, fd, error);
|
||||
}
|
||||
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,179 @@
|
||||
From 5bd5827412a440b074f9f79ae34073e2554ad76c Mon Sep 17 00:00:00 2001
|
||||
From: Simon McVittie <smcv@collabora.com>
|
||||
Date: Thu, 9 Apr 2026 20:06:18 +0100
|
||||
Subject: [PATCH] utils: Move flatpak_get_path_for_fd to here
|
||||
|
||||
This was originally in flatpak-portal, then was duplicated into
|
||||
flatpak-run in commit ac62ebe3 "run: Use O_PATH fds for the runtime and
|
||||
app deploy directories", and subsequently removed from the portal in
|
||||
commit 3c500145 "portal: Use --bind-fd, --app-fd and --usr-fd options to
|
||||
avoid races". Now we want to use it in the portal again.
|
||||
|
||||
Helps: https://github.com/flatpak/flatpak/issues/6584
|
||||
Co-authored-by: Sebastian Wick <sebastian.wick@redhat.com>
|
||||
Signed-off-by: Simon McVittie <smcv@collabora.com>
|
||||
(cherry picked from commit 15dc818874514ffbece4c080405353ed396b54a9)
|
||||
---
|
||||
common/flatpak-run.c | 44 +++---------------------------
|
||||
common/flatpak-utils-private.h | 3 ++
|
||||
common/flatpak-utils.c | 50 ++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 57 insertions(+), 40 deletions(-)
|
||||
|
||||
diff --git a/common/flatpak-run.c b/common/flatpak-run.c
|
||||
index bd6536ac..8ce6978c 100644
|
||||
--- a/common/flatpak-run.c
|
||||
+++ b/common/flatpak-run.c
|
||||
@@ -4108,42 +4108,6 @@ check_sudo (GError **error)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
-static char *
|
||||
-get_path_for_fd (int fd,
|
||||
- GError **error)
|
||||
-{
|
||||
- g_autofree char *proc_path = NULL;
|
||||
- g_autofree char *path = NULL;
|
||||
-
|
||||
- proc_path = g_strdup_printf ("/proc/self/fd/%d", fd);
|
||||
- path = glnx_readlinkat_malloc (AT_FDCWD, proc_path, NULL, error);
|
||||
- if (path == NULL)
|
||||
- return NULL;
|
||||
-
|
||||
- /* All normal paths start with /, but some weird things
|
||||
- don't, such as socket:[27345] or anon_inode:[eventfd].
|
||||
- We don't support any of these */
|
||||
- if (path[0] != '/')
|
||||
- {
|
||||
- return glnx_null_throw (error, "%s resolves to non-absolute path %s",
|
||||
- proc_path, path);
|
||||
- }
|
||||
-
|
||||
- /* File descriptors to actually deleted files have " (deleted)"
|
||||
- appended to them. This also happens to some fake fd types
|
||||
- like shmem which are "/<name> (deleted)". All such
|
||||
- files are considered invalid. Unfortunately this also
|
||||
- matches files with filenames that actually end in " (deleted)",
|
||||
- but there is not much to do about this. */
|
||||
- if (g_str_has_suffix (path, " (deleted)"))
|
||||
- {
|
||||
- return glnx_null_throw (error, "%s resolves to deleted path %s",
|
||||
- proc_path, path);
|
||||
- }
|
||||
-
|
||||
- return g_steal_pointer (&path);
|
||||
-}
|
||||
-
|
||||
gboolean
|
||||
flatpak_run_app (FlatpakDecomposed *app_ref,
|
||||
FlatpakDeploy *app_deploy,
|
||||
@@ -4354,7 +4318,7 @@ flatpak_run_app (FlatpakDecomposed *app_ref,
|
||||
{
|
||||
g_autofree char *path = NULL;
|
||||
|
||||
- path = get_path_for_fd (custom_runtime_fd, &my_error);
|
||||
+ path = flatpak_get_path_for_fd (custom_runtime_fd, &my_error);
|
||||
if (path == NULL)
|
||||
{
|
||||
return flatpak_fail_error (error, FLATPAK_ERROR,
|
||||
@@ -4476,7 +4440,7 @@ flatpak_run_app (FlatpakDecomposed *app_ref,
|
||||
{
|
||||
g_autofree char *path = NULL;
|
||||
|
||||
- path = get_path_for_fd (custom_app_fd, error);
|
||||
+ path = flatpak_get_path_for_fd (custom_app_fd, error);
|
||||
if (path == NULL)
|
||||
return glnx_prefix_error (error, "Cannot convert custom app fd to path");
|
||||
|
||||
@@ -4782,7 +4746,7 @@ flatpak_run_app (FlatpakDecomposed *app_ref,
|
||||
|
||||
/* We get the path the fd refers to, to determine to mount point
|
||||
* destination inside the sandbox */
|
||||
- path = get_path_for_fd (fd, error);
|
||||
+ path = flatpak_get_path_for_fd (fd, error);
|
||||
if (!path)
|
||||
return FALSE;
|
||||
|
||||
@@ -4799,7 +4763,7 @@ flatpak_run_app (FlatpakDecomposed *app_ref,
|
||||
|
||||
/* We get the path the fd refers to, to determine to mount point
|
||||
* destination inside the sandbox */
|
||||
- path = get_path_for_fd (fd, error);
|
||||
+ path = flatpak_get_path_for_fd (fd, error);
|
||||
if (!path)
|
||||
return FALSE;
|
||||
|
||||
diff --git a/common/flatpak-utils-private.h b/common/flatpak-utils-private.h
|
||||
index fd819c71..efe8eb2b 100644
|
||||
--- a/common/flatpak-utils-private.h
|
||||
+++ b/common/flatpak-utils-private.h
|
||||
@@ -930,6 +930,9 @@ gboolean flatpak_validate_path_characters (const char *path,
|
||||
int flatpak_parse_fd (const char *fd_string,
|
||||
GError **error);
|
||||
|
||||
+char * flatpak_get_path_for_fd (int fd,
|
||||
+ GError **error);
|
||||
+
|
||||
#define FLATPAK_MESSAGE_ID "c7b39b1e006b464599465e105b361485"
|
||||
|
||||
gboolean flatpak_set_cloexec (int fd);
|
||||
diff --git a/common/flatpak-utils.c b/common/flatpak-utils.c
|
||||
index 446b3325..6f09fa09 100644
|
||||
--- a/common/flatpak-utils.c
|
||||
+++ b/common/flatpak-utils.c
|
||||
@@ -9227,3 +9227,53 @@ flatpak_set_cloexec (int fd)
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
+
|
||||
+/*
|
||||
+ * Attempt to discover the filesystem path corresponding to @fd.
|
||||
+ *
|
||||
+ * If @fd points to an existing file, return the absolute path of that
|
||||
+ * file in the environment where it was opened. Note that this is not
|
||||
+ * necessarily a valid path in the current namespace, if it was
|
||||
+ * transferred via fd-passing from a process in a different filesystem
|
||||
+ * namespace.
|
||||
+ *
|
||||
+ * If @fd points to a deleted file, or to a socket, fifo, memfd or similar
|
||||
+ * non-filesystem object, set an error and return %NULL.
|
||||
+ *
|
||||
+ * Returns: (type filename) (transfer full) (nullable):
|
||||
+ */
|
||||
+char *
|
||||
+flatpak_get_path_for_fd (int fd,
|
||||
+ GError **error)
|
||||
+{
|
||||
+ g_autofree char *proc_path = NULL;
|
||||
+ g_autofree char *path = NULL;
|
||||
+
|
||||
+ proc_path = g_strdup_printf ("/proc/self/fd/%d", fd);
|
||||
+ path = glnx_readlinkat_malloc (AT_FDCWD, proc_path, NULL, error);
|
||||
+ if (path == NULL)
|
||||
+ return NULL;
|
||||
+
|
||||
+ /* All normal paths start with /, but some weird things
|
||||
+ don't, such as socket:[27345] or anon_inode:[eventfd].
|
||||
+ We don't support any of these */
|
||||
+ if (path[0] != '/')
|
||||
+ {
|
||||
+ return glnx_null_throw (error, "%s resolves to non-absolute path %s",
|
||||
+ proc_path, path);
|
||||
+ }
|
||||
+
|
||||
+ /* File descriptors to actually deleted files have " (deleted)"
|
||||
+ appended to them. This also happens to some fake fd types
|
||||
+ like shmem which are "/<name> (deleted)". All such
|
||||
+ files are considered invalid. Unfortunately this also
|
||||
+ matches files with filenames that actually end in " (deleted)",
|
||||
+ but there is not much to do about this. */
|
||||
+ if (g_str_has_suffix (path, " (deleted)"))
|
||||
+ {
|
||||
+ return glnx_null_throw (error, "%s resolves to deleted path %s",
|
||||
+ proc_path, path);
|
||||
+ }
|
||||
+
|
||||
+ return g_steal_pointer (&path);
|
||||
+}
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,66 @@
|
||||
From 0663652213e742df38528f6c929789189831d40a Mon Sep 17 00:00:00 2001
|
||||
From: Simon McVittie <smcv@collabora.com>
|
||||
Date: Thu, 9 Apr 2026 20:16:16 +0100
|
||||
Subject: [PATCH] portal: Avoid crash if sandbox-expose-[ro-]fd is out of range
|
||||
|
||||
If the handle is not in the range `0 <= handle < fds_len`, but no
|
||||
GError is set, we'd have crashed when we dereferenced error->message.
|
||||
Instead, log an error and early-return, matching what we do for
|
||||
app-fd, usr-fd and the array of inheritable fds.
|
||||
|
||||
Fixes: 3c500145 "portal: Use --bind-fd, --app-fd and --usr-fd options to avoid races"
|
||||
Helps: https://github.com/flatpak/flatpak/issues/6584
|
||||
Co-authored-by: Sebastian Wick <sebastian.wick@redhat.com>
|
||||
Signed-off-by: Simon McVittie <smcv@collabora.com>
|
||||
(cherry picked from commit 4ef2421bd22d8fbf8f17cf9bf5da1dd95aedef8d)
|
||||
---
|
||||
portal/flatpak-portal.c | 26 ++++++++++++++++++++++----
|
||||
1 file changed, 22 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/portal/flatpak-portal.c b/portal/flatpak-portal.c
|
||||
index 59a17b2b..c7310f89 100644
|
||||
--- a/portal/flatpak-portal.c
|
||||
+++ b/portal/flatpak-portal.c
|
||||
@@ -1172,8 +1172,17 @@ handle_spawn (PortalFlatpak *object,
|
||||
gint32 handle;
|
||||
|
||||
g_variant_get_child (sandbox_expose_fd, i, "h", &handle);
|
||||
- if (handle >= 0 && handle < fds_len &&
|
||||
- validate_opath_fd (fds[handle], TRUE, &error))
|
||||
+ if (handle >= fds_len || handle < 0)
|
||||
+ {
|
||||
+ g_debug ("Invalid sandbox-expose-fd handle %d", handle);
|
||||
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||
+ G_DBUS_ERROR_INVALID_ARGS,
|
||||
+ "No file descriptor for handle %d",
|
||||
+ handle);
|
||||
+ return G_DBUS_METHOD_INVOCATION_HANDLED;
|
||||
+ }
|
||||
+
|
||||
+ if (validate_opath_fd (fds[handle], TRUE, &error))
|
||||
{
|
||||
g_array_append_val (expose_fds, fds[handle]);
|
||||
}
|
||||
@@ -1198,8 +1207,17 @@ handle_spawn (PortalFlatpak *object,
|
||||
gint32 handle;
|
||||
|
||||
g_variant_get_child (sandbox_expose_fd_ro, i, "h", &handle);
|
||||
- if (handle >= 0 && handle < fds_len &&
|
||||
- validate_opath_fd (fds[handle], FALSE, &error))
|
||||
+ if (handle >= fds_len || handle < 0)
|
||||
+ {
|
||||
+ g_debug ("Invalid sandbox-expose-ro-fd handle %d", handle);
|
||||
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||
+ G_DBUS_ERROR_INVALID_ARGS,
|
||||
+ "No file descriptor for handle %d",
|
||||
+ handle);
|
||||
+ return G_DBUS_METHOD_INVOCATION_HANDLED;
|
||||
+ }
|
||||
+
|
||||
+ if (validate_opath_fd (fds[handle], FALSE, &error))
|
||||
{
|
||||
g_array_append_val (expose_fds_ro, fds[handle]);
|
||||
}
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,65 @@
|
||||
From db8a36948a0b9d7bc0b7572a969c148f4a704ed4 Mon Sep 17 00:00:00 2001
|
||||
From: Simon McVittie <smcv@collabora.com>
|
||||
Date: Thu, 9 Apr 2026 20:24:48 +0100
|
||||
Subject: [PATCH] portal: Log and ignore unusable sandbox-expose fds instead of
|
||||
erroring
|
||||
|
||||
For the sandbox expose fds, a historical quirk of this code is that if
|
||||
the checks in get_path_for_fd() failed, we would merely log at g_info()
|
||||
level (usually only shown when debugging the portal), and otherwise
|
||||
silently ignore the request to expose the fd in the sandbox.
|
||||
|
||||
With hindsight this was probably not the right thing to do, but apps
|
||||
could well be relying on it now. For example, there are indications
|
||||
that Epiphany might send a memfd from the main instance to a subsandbox,
|
||||
which never actually worked, but will break that subsandbox process
|
||||
if that's treated as a fatal error.
|
||||
|
||||
Fixes: 3c500145 "portal: Use --bind-fd, --app-fd and --usr-fd options to avoid races"
|
||||
Helps: https://github.com/flatpak/flatpak/issues/6584
|
||||
Co-authored-by: Sebastian Wick <sebastian.wick@redhat.com>
|
||||
Signed-off-by: Simon McVittie <smcv@collabora.com>
|
||||
(cherry picked from commit 75ab6eebb857fd26172613b69e55f04830ad0d82)
|
||||
---
|
||||
portal/flatpak-portal.c | 18 ++++++------------
|
||||
1 file changed, 6 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/portal/flatpak-portal.c b/portal/flatpak-portal.c
|
||||
index c7310f89..9f8c7918 100644
|
||||
--- a/portal/flatpak-portal.c
|
||||
+++ b/portal/flatpak-portal.c
|
||||
@@ -1188,12 +1188,9 @@ handle_spawn (PortalFlatpak *object,
|
||||
}
|
||||
else
|
||||
{
|
||||
- g_debug ("Invalid sandbox expose fd: %s", error->message);
|
||||
- g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||
- G_DBUS_ERROR_INVALID_ARGS,
|
||||
- "No valid file descriptor for handle %d",
|
||||
- handle);
|
||||
- return G_DBUS_METHOD_INVOCATION_HANDLED;
|
||||
+ g_info ("unable to validate sandbox-expose-fd %d, ignoring: %s",
|
||||
+ fds[handle], error->message);
|
||||
+ g_clear_error (&error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1223,12 +1220,9 @@ handle_spawn (PortalFlatpak *object,
|
||||
}
|
||||
else
|
||||
{
|
||||
- g_debug ("Invalid sandbox expose ro fd: %s", error->message);
|
||||
- g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||
- G_DBUS_ERROR_INVALID_ARGS,
|
||||
- "No file descriptor for handle %d",
|
||||
- handle);
|
||||
- return G_DBUS_METHOD_INVOCATION_HANDLED;
|
||||
+ g_info ("unable to validate sandbox-expose-ro-fd %d, ignoring: %s",
|
||||
+ fds[handle], error->message);
|
||||
+ g_clear_error (&error);
|
||||
}
|
||||
}
|
||||
}
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,69 @@
|
||||
From df7cfbbed0a0576c35f236ab6ba3620cbfeb900f Mon Sep 17 00:00:00 2001
|
||||
From: Simon McVittie <smcv@collabora.com>
|
||||
Date: Thu, 9 Apr 2026 20:28:57 +0100
|
||||
Subject: [PATCH] portal: Reinstate flatpak_get_path_for_fd() checks
|
||||
|
||||
As with the previous commit, historically we would debug-log but
|
||||
otherwise silently ignore attempts to expose a file in a sandboxed
|
||||
subsandbox that doesn't have a suitable path.
|
||||
|
||||
For example, org.gnome.Epiphany (or possibly WebKitGTK) asks to expose
|
||||
files from /app and /usr in the subsandbox. When we ignored those
|
||||
requests (because /app and /usr have a different meaning on the host
|
||||
system), the app worked as intended anyway, because the subsandbox has
|
||||
access to the app's /app and the runtime's /usr whether they're
|
||||
explicitly added or not, so it all worked out OK. However, treating
|
||||
this as a fatal error (as it arguably should have been) broke
|
||||
Epiphany's subsandboxes.
|
||||
|
||||
Fixes: 3c500145 "portal: Use --bind-fd, --app-fd and --usr-fd options to avoid races"
|
||||
Resolves: https://github.com/flatpak/flatpak/issues/6584
|
||||
Co-authored-by: Sebastian Wick <sebastian.wick@redhat.com>
|
||||
Signed-off-by: Simon McVittie <smcv@collabora.com>
|
||||
(cherry picked from commit 28634c7f52e57df7091007973d1bb5e1f87f1e9d)
|
||||
---
|
||||
portal/flatpak-portal.c | 20 ++++++++++++++++++++
|
||||
1 file changed, 20 insertions(+)
|
||||
|
||||
diff --git a/portal/flatpak-portal.c b/portal/flatpak-portal.c
|
||||
index 9f8c7918..185ed676 100644
|
||||
--- a/portal/flatpak-portal.c
|
||||
+++ b/portal/flatpak-portal.c
|
||||
@@ -556,7 +556,9 @@ validate_opath_fd (int fd,
|
||||
{
|
||||
int fd_flags;
|
||||
struct stat st_buf;
|
||||
+ struct stat real_st_buf;
|
||||
int access_mode;
|
||||
+ g_autofree char *path = NULL;
|
||||
|
||||
/* Must be able to get fd flags */
|
||||
fd_flags = fcntl (fd, F_GETFL);
|
||||
@@ -575,6 +577,24 @@ validate_opath_fd (int fd,
|
||||
if (fstat (fd, &st_buf) < 0)
|
||||
return glnx_throw_errno_prefix (error, "Failed to fstat");
|
||||
|
||||
+ path = flatpak_get_path_for_fd (fd, error);
|
||||
+ if (path == NULL)
|
||||
+ return FALSE;
|
||||
+
|
||||
+ /* Verify that this is the same file as the app opened.
|
||||
+ * Note that this is not security relevant because flatpak-run/bwrap will
|
||||
+ * check things and abort if something is off. We do this only for backwards
|
||||
+ * compatibility reasons: we need to be able to ignore the issue instead of
|
||||
+ * aborting the entire sandbox setup later. */
|
||||
+ if (stat (path, &real_st_buf) < 0 ||
|
||||
+ st_buf.st_dev != real_st_buf.st_dev ||
|
||||
+ st_buf.st_ino != real_st_buf.st_ino)
|
||||
+ {
|
||||
+ /* Different files on the inside and the outside, reject the request */
|
||||
+ return glnx_throw (error,
|
||||
+ "different file inside and outside sandbox");
|
||||
+ }
|
||||
+
|
||||
access_mode = R_OK;
|
||||
if (S_ISDIR (st_buf.st_mode))
|
||||
access_mode |= X_OK;
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,37 @@
|
||||
From 313ceb0cac8d28f941421fabb24e7371b2f3cc8d Mon Sep 17 00:00:00 2001
|
||||
From: Simon McVittie <smcv@collabora.com>
|
||||
Date: Fri, 10 Apr 2026 11:38:12 +0100
|
||||
Subject: [PATCH] libtest: Allow adding a new ref to an existing temporary
|
||||
ostree repo
|
||||
|
||||
When we run `tests/test-run-custom.sh` as a build-time test,
|
||||
we expect to already have the necessary runtimes, apps, etc. in
|
||||
`${builddir}/tests/runtime-repo`. However, when running "as-installed"
|
||||
tests, we're using a fresh temporary ostree repo for each test.
|
||||
Merely having the repo exist is not enough: for some tests, and in
|
||||
particular `tests/test-run-custom.sh`, it needs to have more than one
|
||||
runtime available.
|
||||
|
||||
Resolves: https://github.com/flatpak/flatpak/issues/6591
|
||||
Signed-off-by: Simon McVittie <smcv@collabora.com>
|
||||
(cherry picked from commit 50dda82eb054695b3d3758d0a88ef68c8dd79dc4)
|
||||
---
|
||||
tests/libtest.sh | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/tests/libtest.sh b/tests/libtest.sh
|
||||
index 4a9fd481..5dc4011e 100644
|
||||
--- a/tests/libtest.sh
|
||||
+++ b/tests/libtest.sh
|
||||
@@ -302,7 +302,7 @@ make_runtime () {
|
||||
RUNTIME_REPO=${TEST_DATA_DIR}/runtime-repo
|
||||
(
|
||||
flock -s 200
|
||||
- if [ ! -d ${RUNTIME_REPO} ]; then
|
||||
+ if [ ! -f "${RUNTIME_REPO}/refs/heads/${RUNTIME_REF}" ]; then
|
||||
$(dirname $0)/make-test-runtime.sh ${RUNTIME_REPO} org.test.Platform ${BRANCH} "" "" > /dev/null
|
||||
fi
|
||||
) 200>${TEST_DATA_DIR}/runtime-repo-lock
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,103 @@
|
||||
From 263497107d68e5aa44856b6d1d375fd1adf77879 Mon Sep 17 00:00:00 2001
|
||||
From: Simon McVittie <smcv@collabora.com>
|
||||
Date: Fri, 10 Apr 2026 14:00:14 +0100
|
||||
Subject: [PATCH] app, context: Never close fds 0, 1 or 2
|
||||
|
||||
These fds are stdin, stdout and stderr respectively, and are expected
|
||||
to remain open at all times (if they are not needed then they can point
|
||||
to /dev/null, but they should always be open). If the user gives us
|
||||
`--env-fd=2` or similar, we don't want to close fd 2 before exiting
|
||||
unsuccessfully: that would give us nowhere to display the error message.
|
||||
|
||||
Signed-off-by: Simon McVittie <smcv@collabora.com>
|
||||
(cherry picked from commit c4ab58cd2e66c4bcf193919ef9cbdce1dac042da)
|
||||
---
|
||||
app/flatpak-builtins-run.c | 26 +++++++++++++++++++++-----
|
||||
common/flatpak-context.c | 6 +++++-
|
||||
2 files changed, 26 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/app/flatpak-builtins-run.c b/app/flatpak-builtins-run.c
|
||||
index cc69423e..82725119 100644
|
||||
--- a/app/flatpak-builtins-run.c
|
||||
+++ b/app/flatpak-builtins-run.c
|
||||
@@ -79,7 +79,11 @@ option_bind_fd_cb (const char *option_name,
|
||||
return FALSE;
|
||||
|
||||
if (fd < 3)
|
||||
- return glnx_throw (error, "File descriptors 0, 1, 2 are reserved");
|
||||
+ {
|
||||
+ /* Don't close these fds! */
|
||||
+ fd = -1;
|
||||
+ return glnx_throw (error, "File descriptors 0, 1, 2 are reserved");
|
||||
+ }
|
||||
|
||||
if (!flatpak_set_cloexec (fd))
|
||||
return glnx_throw_errno_prefix (error, "--bind-fd");
|
||||
@@ -102,7 +106,10 @@ option_ro_bind_fd_cb (const char *option_name,
|
||||
return FALSE;
|
||||
|
||||
if (fd < 3)
|
||||
- return glnx_throw (error, "File descriptors 0, 1, 2 are reserved");
|
||||
+ {
|
||||
+ fd = -1;
|
||||
+ return glnx_throw (error, "File descriptors 0, 1, 2 are reserved");
|
||||
+ }
|
||||
|
||||
if (!flatpak_set_cloexec (fd))
|
||||
return glnx_throw_errno_prefix (error, "--ro-bind-fd");
|
||||
@@ -125,7 +132,10 @@ opt_instance_id_fd_cb (const char *option_name,
|
||||
return FALSE;
|
||||
|
||||
if (fd < 3)
|
||||
- return glnx_throw (error, "File descriptors 0, 1, 2 are reserved");
|
||||
+ {
|
||||
+ fd = -1;
|
||||
+ return glnx_throw (error, "File descriptors 0, 1, 2 are reserved");
|
||||
+ }
|
||||
|
||||
if (!flatpak_set_cloexec (fd))
|
||||
return glnx_throw_errno_prefix (error, "--instance-id-fd");
|
||||
@@ -147,7 +157,10 @@ opt_app_fd_cb (const char *option_name,
|
||||
return FALSE;
|
||||
|
||||
if (fd < 3)
|
||||
- return glnx_throw (error, "File descriptors 0, 1, 2 are reserved");
|
||||
+ {
|
||||
+ fd = -1;
|
||||
+ return glnx_throw (error, "File descriptors 0, 1, 2 are reserved");
|
||||
+ }
|
||||
|
||||
if (!flatpak_set_cloexec (fd))
|
||||
return glnx_throw_errno_prefix (error, "--app-fd");
|
||||
@@ -169,7 +182,10 @@ opt_usr_fd_cb (const char *option_name,
|
||||
return FALSE;
|
||||
|
||||
if (fd < 3)
|
||||
- return glnx_throw (error, "File descriptors 0, 1, 2 are reserved");
|
||||
+ {
|
||||
+ fd = -1;
|
||||
+ return glnx_throw (error, "File descriptors 0, 1, 2 are reserved");
|
||||
+ }
|
||||
|
||||
if (!flatpak_set_cloexec (fd))
|
||||
return glnx_throw_errno_prefix (error, "--usr-fd");
|
||||
diff --git a/common/flatpak-context.c b/common/flatpak-context.c
|
||||
index 3ff4ac16..3dc8f533 100644
|
||||
--- a/common/flatpak-context.c
|
||||
+++ b/common/flatpak-context.c
|
||||
@@ -1311,7 +1311,11 @@ option_env_fd_cb (const gchar *option_name,
|
||||
return FALSE;
|
||||
|
||||
if (fd < 3)
|
||||
- return glnx_throw (error, "File descriptors 0, 1, 2 are reserved");
|
||||
+ {
|
||||
+ /* Don't close these fds! */
|
||||
+ fd = -1;
|
||||
+ return glnx_throw (error, "File descriptors 0, 1, 2 are reserved");
|
||||
+ }
|
||||
|
||||
/* This is not strictly necessary, because we're going to close it after
|
||||
* parsing the environment block, but let's be consistent with other fd
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,235 @@
|
||||
From 9c357f7f9d4d781bf04dafab9559343e9ec44f55 Mon Sep 17 00:00:00 2001
|
||||
From: Simon McVittie <smcv@collabora.com>
|
||||
Date: Fri, 10 Apr 2026 15:02:43 +0100
|
||||
Subject: [PATCH] app, context: Factor out flatpak_accept_fd_argument()
|
||||
|
||||
Signed-off-by: Simon McVittie <smcv@collabora.com>
|
||||
(cherry picked from commit d42037c5267ac7967ce285b9052b25fe7a968368)
|
||||
---
|
||||
app/flatpak-builtins-run.c | 61 ++++++----------------------------
|
||||
common/flatpak-context.c | 18 ++--------
|
||||
common/flatpak-utils-private.h | 4 +++
|
||||
common/flatpak-utils.c | 47 ++++++++++++++++++++++++++
|
||||
4 files changed, 63 insertions(+), 67 deletions(-)
|
||||
|
||||
diff --git a/app/flatpak-builtins-run.c b/app/flatpak-builtins-run.c
|
||||
index 82725119..c9e7e071 100644
|
||||
--- a/app/flatpak-builtins-run.c
|
||||
+++ b/app/flatpak-builtins-run.c
|
||||
@@ -74,20 +74,11 @@ option_bind_fd_cb (const char *option_name,
|
||||
{
|
||||
glnx_autofd int fd = -1;
|
||||
|
||||
- fd = flatpak_parse_fd (value, error);
|
||||
+ fd = flatpak_accept_fd_argument (option_name, value, error);
|
||||
+
|
||||
if (fd < 0)
|
||||
return FALSE;
|
||||
|
||||
- if (fd < 3)
|
||||
- {
|
||||
- /* Don't close these fds! */
|
||||
- fd = -1;
|
||||
- return glnx_throw (error, "File descriptors 0, 1, 2 are reserved");
|
||||
- }
|
||||
-
|
||||
- if (!flatpak_set_cloexec (fd))
|
||||
- return glnx_throw_errno_prefix (error, "--bind-fd");
|
||||
-
|
||||
g_array_append_val (opt_bind_fds, fd);
|
||||
fd = -1; /* ownership transferred to GArray */
|
||||
return TRUE;
|
||||
@@ -101,19 +92,11 @@ option_ro_bind_fd_cb (const char *option_name,
|
||||
{
|
||||
glnx_autofd int fd = -1;
|
||||
|
||||
- fd = flatpak_parse_fd (value, error);
|
||||
+ fd = flatpak_accept_fd_argument (option_name, value, error);
|
||||
+
|
||||
if (fd < 0)
|
||||
return FALSE;
|
||||
|
||||
- if (fd < 3)
|
||||
- {
|
||||
- fd = -1;
|
||||
- return glnx_throw (error, "File descriptors 0, 1, 2 are reserved");
|
||||
- }
|
||||
-
|
||||
- if (!flatpak_set_cloexec (fd))
|
||||
- return glnx_throw_errno_prefix (error, "--ro-bind-fd");
|
||||
-
|
||||
g_array_append_val (opt_ro_bind_fds, fd);
|
||||
fd = -1; /* ownership transferred to GArray */
|
||||
return TRUE;
|
||||
@@ -127,19 +110,11 @@ opt_instance_id_fd_cb (const char *option_name,
|
||||
{
|
||||
glnx_autofd int fd = -1;
|
||||
|
||||
- fd = flatpak_parse_fd (value, error);
|
||||
+ fd = flatpak_accept_fd_argument (option_name, value, error);
|
||||
+
|
||||
if (fd < 0)
|
||||
return FALSE;
|
||||
|
||||
- if (fd < 3)
|
||||
- {
|
||||
- fd = -1;
|
||||
- return glnx_throw (error, "File descriptors 0, 1, 2 are reserved");
|
||||
- }
|
||||
-
|
||||
- if (!flatpak_set_cloexec (fd))
|
||||
- return glnx_throw_errno_prefix (error, "--instance-id-fd");
|
||||
-
|
||||
opt_instance_id_fd = g_steal_fd (&fd);
|
||||
return TRUE;
|
||||
}
|
||||
@@ -152,19 +127,11 @@ opt_app_fd_cb (const char *option_name,
|
||||
{
|
||||
glnx_autofd int fd = -1;
|
||||
|
||||
- fd = flatpak_parse_fd (value, error);
|
||||
+ fd = flatpak_accept_fd_argument (option_name, value, error);
|
||||
+
|
||||
if (fd < 0)
|
||||
return FALSE;
|
||||
|
||||
- if (fd < 3)
|
||||
- {
|
||||
- fd = -1;
|
||||
- return glnx_throw (error, "File descriptors 0, 1, 2 are reserved");
|
||||
- }
|
||||
-
|
||||
- if (!flatpak_set_cloexec (fd))
|
||||
- return glnx_throw_errno_prefix (error, "--app-fd");
|
||||
-
|
||||
opt_app_fd = g_steal_fd (&fd);
|
||||
return TRUE;
|
||||
}
|
||||
@@ -177,19 +144,11 @@ opt_usr_fd_cb (const char *option_name,
|
||||
{
|
||||
glnx_autofd int fd = -1;
|
||||
|
||||
- fd = flatpak_parse_fd (value, error);
|
||||
+ fd = flatpak_accept_fd_argument (option_name, value, error);
|
||||
+
|
||||
if (fd < 0)
|
||||
return FALSE;
|
||||
|
||||
- if (fd < 3)
|
||||
- {
|
||||
- fd = -1;
|
||||
- return glnx_throw (error, "File descriptors 0, 1, 2 are reserved");
|
||||
- }
|
||||
-
|
||||
- if (!flatpak_set_cloexec (fd))
|
||||
- return glnx_throw_errno_prefix (error, "--usr-fd");
|
||||
-
|
||||
opt_usr_fd = g_steal_fd (&fd);
|
||||
return TRUE;
|
||||
}
|
||||
diff --git a/common/flatpak-context.c b/common/flatpak-context.c
|
||||
index 3dc8f533..2165631d 100644
|
||||
--- a/common/flatpak-context.c
|
||||
+++ b/common/flatpak-context.c
|
||||
@@ -1306,25 +1306,11 @@ option_env_fd_cb (const gchar *option_name,
|
||||
FlatpakContext *context = data;
|
||||
glnx_autofd int fd = -1;
|
||||
|
||||
- fd = flatpak_parse_fd (value, error);
|
||||
+ fd = flatpak_accept_fd_argument (option_name, value, error);
|
||||
+
|
||||
if (fd < 0)
|
||||
return FALSE;
|
||||
|
||||
- if (fd < 3)
|
||||
- {
|
||||
- /* Don't close these fds! */
|
||||
- fd = -1;
|
||||
- return glnx_throw (error, "File descriptors 0, 1, 2 are reserved");
|
||||
- }
|
||||
-
|
||||
- /* This is not strictly necessary, because we're going to close it after
|
||||
- * parsing the environment block, but let's be consistent with other fd
|
||||
- * arguments that we need to avoid being inherited by the "payload"
|
||||
- * command. This is also a convenient place to validate that it's an
|
||||
- * open fd. */
|
||||
- if (!flatpak_set_cloexec (fd))
|
||||
- return glnx_throw_errno_prefix (error, "--env-fd");
|
||||
-
|
||||
return flatpak_context_parse_env_fd (context, fd, error);
|
||||
}
|
||||
|
||||
diff --git a/common/flatpak-utils-private.h b/common/flatpak-utils-private.h
|
||||
index efe8eb2b..215b3c38 100644
|
||||
--- a/common/flatpak-utils-private.h
|
||||
+++ b/common/flatpak-utils-private.h
|
||||
@@ -937,4 +937,8 @@ char * flatpak_get_path_for_fd (int fd,
|
||||
|
||||
gboolean flatpak_set_cloexec (int fd);
|
||||
|
||||
+int flatpak_accept_fd_argument (const char *option_name,
|
||||
+ const char *value,
|
||||
+ GError **error);
|
||||
+
|
||||
#endif /* __FLATPAK_UTILS_H__ */
|
||||
diff --git a/common/flatpak-utils.c b/common/flatpak-utils.c
|
||||
index 6f09fa09..63a2e325 100644
|
||||
--- a/common/flatpak-utils.c
|
||||
+++ b/common/flatpak-utils.c
|
||||
@@ -9228,6 +9228,53 @@ flatpak_set_cloexec (int fd)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * flatpak_accept_fd_argument:
|
||||
+ * @option_name: Name of a command-line option such as `--env-fd`
|
||||
+ * @value: Value of the command-line option
|
||||
+ *
|
||||
+ * Parse a command-line argument whose value is a file descriptor to be
|
||||
+ * used internally by Flatpak.
|
||||
+ *
|
||||
+ * The file descriptor must be 3 or higher (cannot be stdin, stdout
|
||||
+ * or stderr).
|
||||
+ *
|
||||
+ * The file descriptor is set to be close-on-execute (CLOEXEC).
|
||||
+ * If child processes are meant to inherit it, the caller must clear the
|
||||
+ * close-on-execute flag, or duplicate the fd.
|
||||
+ *
|
||||
+ * Returns: A file descriptor to be closed by the caller, or -1 on error
|
||||
+ */
|
||||
+int
|
||||
+flatpak_accept_fd_argument (const char *option_name,
|
||||
+ const char *value,
|
||||
+ GError **error)
|
||||
+{
|
||||
+ glnx_autofd int fd = -1;
|
||||
+
|
||||
+ fd = flatpak_parse_fd (value, error);
|
||||
+
|
||||
+ if (fd < 0)
|
||||
+ {
|
||||
+ g_prefix_error (error, "%s: ", option_name);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if (fd < 3)
|
||||
+ {
|
||||
+ /* We don't want to close stdin, stdout or stderr */
|
||||
+ fd = -1;
|
||||
+ return glnx_fd_throw (error,
|
||||
+ "%s: Cannot use reserved file descriptor 0, 1 or 2",
|
||||
+ option_name);
|
||||
+ }
|
||||
+
|
||||
+ if (!flatpak_set_cloexec (fd))
|
||||
+ return glnx_fd_throw_errno_prefix (error, "%s", option_name);
|
||||
+
|
||||
+ return g_steal_fd (&fd);
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Attempt to discover the filesystem path corresponding to @fd.
|
||||
*
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,48 @@
|
||||
From ba43f074af594705b0aea9f53261d3b61fc3c866 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Wick <sebastian.wick@redhat.com>
|
||||
Date: Fri, 6 Feb 2026 16:32:50 +0100
|
||||
Subject: [PATCH] flatpak-bwrap: Use glnx_close_fd as clear func
|
||||
|
||||
We already have a function which clears a fd that a pointer points to,
|
||||
so let's use it instead of duplicating the code.
|
||||
|
||||
Will become useful in a later commit as well.
|
||||
---
|
||||
common/flatpak-bwrap.c | 13 ++-----------
|
||||
1 file changed, 2 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/common/flatpak-bwrap.c b/common/flatpak-bwrap.c
|
||||
index 1694ffd4..693a1981 100644
|
||||
--- a/common/flatpak-bwrap.c
|
||||
+++ b/common/flatpak-bwrap.c
|
||||
@@ -41,15 +41,6 @@
|
||||
#include "flatpak-utils-private.h"
|
||||
#include "flatpak-utils-base-private.h"
|
||||
|
||||
-static void
|
||||
-clear_fd (gpointer data)
|
||||
-{
|
||||
- int *fd_p = data;
|
||||
-
|
||||
- if (fd_p != NULL && *fd_p != -1)
|
||||
- close (*fd_p);
|
||||
-}
|
||||
-
|
||||
char *flatpak_bwrap_empty_env[] = { NULL };
|
||||
|
||||
FlatpakBwrap *
|
||||
@@ -59,9 +50,9 @@ flatpak_bwrap_new (char **env)
|
||||
|
||||
bwrap->argv = g_ptr_array_new_with_free_func (g_free);
|
||||
bwrap->noinherit_fds = g_array_new (FALSE, TRUE, sizeof (int));
|
||||
- g_array_set_clear_func (bwrap->noinherit_fds, clear_fd);
|
||||
+ g_array_set_clear_func (bwrap->noinherit_fds, (GDestroyNotify) glnx_close_fd);
|
||||
bwrap->fds = g_array_new (FALSE, TRUE, sizeof (int));
|
||||
- g_array_set_clear_func (bwrap->fds, clear_fd);
|
||||
+ g_array_set_clear_func (bwrap->fds, (GDestroyNotify) glnx_close_fd);
|
||||
|
||||
if (env)
|
||||
bwrap->envp = g_strdupv (env);
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,912 @@
|
||||
From f41f12c98896aced62830bf5f3e21c40ee24a6d7 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Wick <sebastian.wick@redhat.com>
|
||||
Date: Fri, 6 Feb 2026 20:54:22 +0100
|
||||
Subject: [PATCH] run: Use O_PATH fds for the runtime and app deploy
|
||||
directories
|
||||
|
||||
This also allows us to use glnx_chaseat, and other at-functions to
|
||||
traverse the filesystem tree in a safe way.
|
||||
|
||||
This is important because the app and runtime deploy directories can be
|
||||
under an attackers control. The flatpak portal for example allows
|
||||
sandboxed apps to provide them.
|
||||
|
||||
In particular, attacks where the deploy dirs get replaced by a symlink
|
||||
pointing into the host system will be stopped by this.
|
||||
|
||||
Note that this change alone is not enough to avoid the attack, and the
|
||||
portal has to be changed as well.
|
||||
---
|
||||
app/flatpak-builtins-build.c | 8 +-
|
||||
app/flatpak-builtins-run.c | 37 ++-
|
||||
common/Makefile.am.inc | 2 +-
|
||||
common/flatpak-dir.c | 8 +-
|
||||
common/flatpak-installation.c | 3 +-
|
||||
common/flatpak-run-private.h | 11 +-
|
||||
common/flatpak-run.c | 452 +++++++++++++++++++++++-----------
|
||||
7 files changed, 372 insertions(+), 149 deletions(-)
|
||||
|
||||
diff --git a/app/flatpak-builtins-build.c b/app/flatpak-builtins-build.c
|
||||
index 4a1e762..09b469a 100644
|
||||
--- a/app/flatpak-builtins-build.c
|
||||
+++ b/app/flatpak-builtins-build.c
|
||||
@@ -457,7 +457,13 @@ flatpak_builtin_build (int argc, char **argv, GCancellable *cancellable, GError
|
||||
/* Never set up an a11y bus for builds */
|
||||
run_flags |= FLATPAK_RUN_FLAG_NO_A11Y_BUS_PROXY;
|
||||
|
||||
- if (!flatpak_run_setup_base_argv (bwrap, runtime_files, app_id_dir, arch,
|
||||
+ glnx_autofd int usr_fd = -1;
|
||||
+ usr_fd = open (flatpak_file_get_path_cached (runtime_files),
|
||||
+ O_PATH | O_CLOEXEC | O_NOFOLLOW);
|
||||
+ if (usr_fd < 0)
|
||||
+ return glnx_throw_errno_prefix (error, "Failed to open runtime files");
|
||||
+
|
||||
+ if (!flatpak_run_setup_base_argv (bwrap, usr_fd, app_id_dir, arch,
|
||||
run_flags, error))
|
||||
return FALSE;
|
||||
|
||||
diff --git a/app/flatpak-builtins-run.c b/app/flatpak-builtins-run.c
|
||||
index ba2ae67..9403d8a 100644
|
||||
--- a/app/flatpak-builtins-run.c
|
||||
+++ b/app/flatpak-builtins-run.c
|
||||
@@ -110,6 +110,8 @@ flatpak_builtin_run (int argc, char **argv, GCancellable *cancellable, GError **
|
||||
g_autoptr(GError) local_error = NULL;
|
||||
g_autoptr(GPtrArray) dirs = NULL;
|
||||
FlatpakRunFlags flags = 0;
|
||||
+ glnx_autofd int app_fd = -1;
|
||||
+ glnx_autofd int usr_fd = -1;
|
||||
|
||||
context = g_option_context_new (_("APP [ARGUMENT…] - Run an app"));
|
||||
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
|
||||
@@ -305,14 +307,45 @@ flatpak_builtin_run (int argc, char **argv, GCancellable *cancellable, GError **
|
||||
if (!opt_session_bus)
|
||||
flags |= FLATPAK_RUN_FLAG_NO_SESSION_BUS_PROXY;
|
||||
|
||||
+ if (opt_app_path != NULL)
|
||||
+ {
|
||||
+ if (g_strcmp0 (opt_app_path, "") == 0)
|
||||
+ {
|
||||
+ app_fd = FLATPAK_RUN_APP_DEPLOY_APP_EMPTY;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ app_fd = open (opt_app_path, O_PATH | O_CLOEXEC | O_NOFOLLOW);
|
||||
+
|
||||
+ if (app_fd < 0)
|
||||
+ return glnx_throw_errno_prefix (error, "Failed to open app-path");
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ app_fd = FLATPAK_RUN_APP_DEPLOY_APP_ORIGINAL;
|
||||
+ }
|
||||
+
|
||||
+ if (opt_usr_path != NULL)
|
||||
+ {
|
||||
+ usr_fd = open (opt_usr_path, O_PATH | O_CLOEXEC | O_NOFOLLOW);
|
||||
+
|
||||
+ if (usr_fd < 0)
|
||||
+ return glnx_throw_errno_prefix (error, "Failed to open usr-path");
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ usr_fd = FLATPAK_RUN_APP_DEPLOY_USR_ORIGINAL;
|
||||
+ }
|
||||
+
|
||||
if (!flatpak_run_app (app_deploy ? app_ref : runtime_ref,
|
||||
app_deploy,
|
||||
- opt_app_path,
|
||||
+ app_fd,
|
||||
arg_context,
|
||||
opt_runtime,
|
||||
opt_runtime_version,
|
||||
opt_runtime_commit,
|
||||
- opt_usr_path,
|
||||
+ usr_fd,
|
||||
opt_parent_pid,
|
||||
flags,
|
||||
opt_cwd,
|
||||
diff --git a/common/Makefile.am.inc b/common/Makefile.am.inc
|
||||
index 892ee4c..3147cc7 100644
|
||||
--- a/common/Makefile.am.inc
|
||||
+++ b/common/Makefile.am.inc
|
||||
@@ -205,6 +205,7 @@ libflatpak_common_la_CFLAGS = \
|
||||
$(NULL)
|
||||
libflatpak_common_la_LIBADD = \
|
||||
$(AM_LIBADD) \
|
||||
+ libglnx.la \
|
||||
$(ARCHIVE_LIBS) \
|
||||
$(ZSTD_LIBS) \
|
||||
$(BASE_LIBS) \
|
||||
@@ -249,7 +250,6 @@ libflatpak_la_LIBADD = \
|
||||
$(AM_LIBADD) \
|
||||
libflatpak-common.la \
|
||||
libflatpak-common-base.la \
|
||||
- libglnx.la \
|
||||
$(BASE_LIBS) \
|
||||
$(OSTREE_LIBS) \
|
||||
$(SOUP_LIBS) \
|
||||
diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c
|
||||
index 978df03..c18fd44 100644
|
||||
--- a/common/flatpak-dir.c
|
||||
+++ b/common/flatpak-dir.c
|
||||
@@ -8014,7 +8014,13 @@ apply_extra_data (FlatpakDir *self,
|
||||
"--cap-drop", "ALL",
|
||||
NULL);
|
||||
|
||||
- if (!flatpak_run_setup_base_argv (bwrap, runtime_files, NULL, runtime_arch,
|
||||
+ glnx_autofd int usr_fd = -1;
|
||||
+ usr_fd = open (flatpak_file_get_path_cached (runtime_files),
|
||||
+ O_PATH | O_CLOEXEC | O_NOFOLLOW);
|
||||
+ if (usr_fd < 0)
|
||||
+ return glnx_throw_errno_prefix (error, "Failed to open runtime files");
|
||||
+
|
||||
+ if (!flatpak_run_setup_base_argv (bwrap, usr_fd, NULL, runtime_arch,
|
||||
/* Might need multiarch in apply_extra (see e.g. #3742). Should be pretty safe in this limited context */
|
||||
FLATPAK_RUN_FLAG_MULTIARCH |
|
||||
FLATPAK_RUN_FLAG_NO_SESSION_HELPER | FLATPAK_RUN_FLAG_NO_PROC,
|
||||
diff --git a/common/flatpak-installation.c b/common/flatpak-installation.c
|
||||
index 3c5a12a..9254252 100644
|
||||
--- a/common/flatpak-installation.c
|
||||
+++ b/common/flatpak-installation.c
|
||||
@@ -700,9 +700,10 @@ flatpak_installation_launch_full (FlatpakInstallation *self,
|
||||
|
||||
if (!flatpak_run_app (app_ref,
|
||||
app_deploy,
|
||||
+ FLATPAK_RUN_APP_DEPLOY_APP_ORIGINAL,
|
||||
NULL,
|
||||
- NULL, NULL,
|
||||
NULL, NULL, NULL,
|
||||
+ FLATPAK_RUN_APP_DEPLOY_USR_ORIGINAL,
|
||||
0,
|
||||
run_flags,
|
||||
NULL,
|
||||
diff --git a/common/flatpak-run-private.h b/common/flatpak-run-private.h
|
||||
index eac25cc..5fc1f29 100644
|
||||
--- a/common/flatpak-run-private.h
|
||||
+++ b/common/flatpak-run-private.h
|
||||
@@ -28,6 +28,11 @@
|
||||
#include "flatpak-utils-private.h"
|
||||
#include "flatpak-exports-private.h"
|
||||
|
||||
+#define FLATPAK_RUN_APP_DEPLOY_APP_ORIGINAL (-2)
|
||||
+#define FLATPAK_RUN_APP_DEPLOY_APP_EMPTY (-3)
|
||||
+
|
||||
+#define FLATPAK_RUN_APP_DEPLOY_USR_ORIGINAL (-2)
|
||||
+
|
||||
gboolean flatpak_run_in_transient_unit (const char *app_id,
|
||||
GError **error);
|
||||
|
||||
@@ -151,7 +156,7 @@ gboolean flatpak_ensure_data_dir (GFile *app_id_dir,
|
||||
GError **error);
|
||||
|
||||
gboolean flatpak_run_setup_base_argv (FlatpakBwrap *bwrap,
|
||||
- GFile *runtime_files,
|
||||
+ int runtime_fd,
|
||||
GFile *app_id_dir,
|
||||
const char *arch,
|
||||
FlatpakRunFlags flags,
|
||||
@@ -181,12 +186,12 @@ gboolean flatpak_run_add_app_info_args (FlatpakBwrap *bwrap,
|
||||
|
||||
gboolean flatpak_run_app (FlatpakDecomposed *app_ref,
|
||||
FlatpakDeploy *app_deploy,
|
||||
- const char *custom_app_path,
|
||||
+ int custom_app_fd,
|
||||
FlatpakContext *extra_context,
|
||||
const char *custom_runtime,
|
||||
const char *custom_runtime_version,
|
||||
const char *custom_runtime_commit,
|
||||
- const char *custom_usr_path,
|
||||
+ int custom_runtime_fd,
|
||||
int parent_pid,
|
||||
FlatpakRunFlags flags,
|
||||
const char *cwd,
|
||||
diff --git a/common/flatpak-run.c b/common/flatpak-run.c
|
||||
index 4fdb56f..0e1d16f 100644
|
||||
--- a/common/flatpak-run.c
|
||||
+++ b/common/flatpak-run.c
|
||||
@@ -2846,19 +2846,37 @@ flatpak_run_add_app_info_args (FlatpakBwrap *bwrap,
|
||||
|
||||
static void
|
||||
add_tzdata_args (FlatpakBwrap *bwrap,
|
||||
- GFile *runtime_files)
|
||||
+ int runtime_fd)
|
||||
{
|
||||
- g_autofree char *raw_timezone = flatpak_get_timezone ();
|
||||
- g_autofree char *timezone_content = g_strdup_printf ("%s\n", raw_timezone);
|
||||
- g_autofree char *localtime_content = g_strconcat ("../usr/share/zoneinfo/", raw_timezone, NULL);
|
||||
- g_autoptr(GFile) runtime_zoneinfo = NULL;
|
||||
+ g_autofree char *raw_timezone = NULL;
|
||||
+ g_autofree char *timezone_content = NULL;
|
||||
+ g_autofree char *localtime_content = NULL;
|
||||
+ glnx_autofd int zoneinfo_fd = -1;
|
||||
+ g_autofree char *runtime_zoneinfo = NULL;
|
||||
+ g_autoptr(GError) error = NULL;
|
||||
+
|
||||
+ raw_timezone = flatpak_get_timezone ();
|
||||
+ timezone_content = g_strdup_printf ("%s\n", raw_timezone);
|
||||
+ localtime_content = g_strconcat ("../usr/share/zoneinfo/", raw_timezone, NULL);
|
||||
+
|
||||
+ zoneinfo_fd = glnx_chaseat (runtime_fd, "share/zoneinfo",
|
||||
+ GLNX_CHASE_RESOLVE_BENEATH |
|
||||
+ GLNX_CHASE_MUST_BE_DIRECTORY,
|
||||
+ NULL);
|
||||
|
||||
- if (runtime_files)
|
||||
- runtime_zoneinfo = g_file_resolve_relative_path (runtime_files, "share/zoneinfo");
|
||||
+ runtime_zoneinfo = g_strconcat ("share/zoneinfo/", raw_timezone, NULL);
|
||||
|
||||
/* Check for runtime /usr/share/zoneinfo */
|
||||
- if (runtime_zoneinfo != NULL && g_file_query_exists (runtime_zoneinfo, NULL))
|
||||
+ if (zoneinfo_fd >= 0)
|
||||
{
|
||||
+ glnx_autofd int runtime_zoneinfo_fd = -1;
|
||||
+
|
||||
+ /* Check for runtime /usr/share/zoneinfo */
|
||||
+ runtime_zoneinfo_fd = glnx_chaseat (runtime_fd, runtime_zoneinfo,
|
||||
+ GLNX_CHASE_RESOLVE_BENEATH |
|
||||
+ GLNX_CHASE_MUST_BE_REGULAR,
|
||||
+ NULL);
|
||||
+
|
||||
/* Check for host /usr/share/zoneinfo */
|
||||
if (g_file_test ("/usr/share/zoneinfo", G_FILE_TEST_IS_DIR))
|
||||
{
|
||||
@@ -2868,15 +2886,12 @@ add_tzdata_args (FlatpakBwrap *bwrap,
|
||||
"--symlink", localtime_content, "/etc/localtime",
|
||||
NULL);
|
||||
}
|
||||
- else
|
||||
+ /* Check if host timezone file exist in the runtime tzdata */
|
||||
+ else if (runtime_zoneinfo_fd >= 0)
|
||||
{
|
||||
- g_autoptr(GFile) runtime_tzfile = g_file_resolve_relative_path (runtime_zoneinfo, raw_timezone);
|
||||
-
|
||||
- /* Check if host timezone file exist in the runtime tzdata */
|
||||
- if (g_file_query_exists (runtime_tzfile, NULL))
|
||||
- flatpak_bwrap_add_args (bwrap,
|
||||
- "--symlink", localtime_content, "/etc/localtime",
|
||||
- NULL);
|
||||
+ flatpak_bwrap_add_args (bwrap,
|
||||
+ "--symlink", localtime_content, "/etc/localtime",
|
||||
+ NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3359,24 +3374,41 @@ setup_seccomp (FlatpakBwrap *bwrap,
|
||||
|
||||
static void
|
||||
flatpak_run_setup_usr_links (FlatpakBwrap *bwrap,
|
||||
- GFile *runtime_files,
|
||||
+ int runtime_fd,
|
||||
const char *sysroot)
|
||||
{
|
||||
int i;
|
||||
|
||||
- if (runtime_files == NULL)
|
||||
+ g_return_if_fail (runtime_fd >= -1);
|
||||
+
|
||||
+ if (runtime_fd < 0)
|
||||
return;
|
||||
|
||||
for (i = 0; flatpak_abs_usrmerged_dirs[i] != NULL; i++)
|
||||
{
|
||||
const char *subdir = flatpak_abs_usrmerged_dirs[i];
|
||||
- g_autoptr(GFile) runtime_subdir = NULL;
|
||||
+ glnx_autofd int runtime_subdir_fd = -1;
|
||||
+ g_autoptr(GError) local_error = NULL;
|
||||
|
||||
g_assert (subdir[0] == '/');
|
||||
+
|
||||
/* Skip the '/' when using as a subdirectory of the runtime */
|
||||
- runtime_subdir = g_file_get_child (runtime_files, subdir + 1);
|
||||
+ runtime_subdir_fd = glnx_chaseat (runtime_fd, subdir + 1,
|
||||
+ GLNX_CHASE_RESOLVE_BENEATH |
|
||||
+ GLNX_CHASE_NOFOLLOW,
|
||||
+ &local_error);
|
||||
|
||||
- if (g_file_query_exists (runtime_subdir, NULL))
|
||||
+ if (runtime_subdir_fd < 0 &&
|
||||
+ !g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
|
||||
+ {
|
||||
+ g_warning ("Checking for usrmerged dir %s failed: %s",
|
||||
+ subdir, local_error->message);
|
||||
+ }
|
||||
+ else if (runtime_subdir_fd < 0)
|
||||
+ {
|
||||
+ g_debug ("%s does not exist in runtime", subdir);
|
||||
+ }
|
||||
+ else
|
||||
{
|
||||
g_autofree char *link = g_strconcat ("usr", subdir, NULL);
|
||||
g_autofree char *create = NULL;
|
||||
@@ -3390,17 +3422,12 @@ flatpak_run_setup_usr_links (FlatpakBwrap *bwrap,
|
||||
"--symlink", link, create,
|
||||
NULL);
|
||||
}
|
||||
- else
|
||||
- {
|
||||
- g_debug ("%s does not exist",
|
||||
- flatpak_file_get_path_cached (runtime_subdir));
|
||||
- }
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
flatpak_run_setup_base_argv (FlatpakBwrap *bwrap,
|
||||
- GFile *runtime_files,
|
||||
+ int runtime_fd,
|
||||
GFile *app_id_dir,
|
||||
const char *arch,
|
||||
FlatpakRunFlags flags,
|
||||
@@ -3413,7 +3440,6 @@ flatpak_run_setup_base_argv (FlatpakBwrap *bwrap,
|
||||
struct group *g;
|
||||
gulong pers;
|
||||
gid_t gid = getgid ();
|
||||
- g_autoptr(GFile) etc = NULL;
|
||||
|
||||
run_dir = g_strdup_printf ("/run/user/%d", getuid ());
|
||||
|
||||
@@ -3488,22 +3514,25 @@ flatpak_run_setup_base_argv (FlatpakBwrap *bwrap,
|
||||
else if (g_file_test ("/var/lib/dbus/machine-id", G_FILE_TEST_EXISTS))
|
||||
flatpak_bwrap_add_args (bwrap, "--ro-bind", "/var/lib/dbus/machine-id", "/etc/machine-id", NULL);
|
||||
|
||||
- if (runtime_files)
|
||||
- etc = g_file_get_child (runtime_files, "etc");
|
||||
- if (etc != NULL &&
|
||||
- (flags & FLATPAK_RUN_FLAG_WRITABLE_ETC) == 0 &&
|
||||
- g_file_query_exists (etc, NULL))
|
||||
+ if ((flags & FLATPAK_RUN_FLAG_WRITABLE_ETC) == 0)
|
||||
{
|
||||
g_auto(GLnxDirFdIterator) dfd_iter = { 0, };
|
||||
struct dirent *dent;
|
||||
gboolean inited;
|
||||
+ g_autoptr(GError) local_error = NULL;
|
||||
|
||||
- inited = glnx_dirfd_iterator_init_at (AT_FDCWD, flatpak_file_get_path_cached (etc), FALSE, &dfd_iter, NULL);
|
||||
+ inited = glnx_dirfd_iterator_init_at (runtime_fd, "etc", FALSE, &dfd_iter, &local_error);
|
||||
+ if (!inited && !g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
|
||||
+ {
|
||||
+ g_propagate_error (error, g_steal_pointer (&local_error));
|
||||
+ return FALSE;
|
||||
+ }
|
||||
|
||||
while (inited)
|
||||
{
|
||||
- g_autofree char *src = NULL;
|
||||
g_autofree char *dest = NULL;
|
||||
+ glnx_autofd int src_fd = -1;
|
||||
+ struct stat statbuf;
|
||||
|
||||
if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&dfd_iter, &dent, NULL, NULL) || dent == NULL)
|
||||
break;
|
||||
@@ -3520,9 +3549,19 @@ flatpak_run_setup_base_argv (FlatpakBwrap *bwrap,
|
||||
strcmp (dent->d_name, "pkcs11") == 0)
|
||||
continue;
|
||||
|
||||
- src = g_build_filename (flatpak_file_get_path_cached (etc), dent->d_name, NULL);
|
||||
dest = g_build_filename ("/etc", dent->d_name, NULL);
|
||||
- if (dent->d_type == DT_LNK)
|
||||
+
|
||||
+ src_fd = glnx_chaseat (dfd_iter.fd, dent->d_name,
|
||||
+ GLNX_CHASE_NOFOLLOW |
|
||||
+ GLNX_CHASE_RESOLVE_BENEATH,
|
||||
+ error);
|
||||
+ if (src_fd < 0)
|
||||
+ return FALSE;
|
||||
+
|
||||
+ if (!glnx_fstat (src_fd, &statbuf, error))
|
||||
+ return FALSE;
|
||||
+
|
||||
+ if (S_ISLNK (statbuf.st_mode))
|
||||
{
|
||||
g_autofree char *target = NULL;
|
||||
|
||||
@@ -3533,9 +3572,12 @@ flatpak_run_setup_base_argv (FlatpakBwrap *bwrap,
|
||||
|
||||
flatpak_bwrap_add_args (bwrap, "--symlink", target, dest, NULL);
|
||||
}
|
||||
- else
|
||||
+ else if (src_fd >= 0)
|
||||
{
|
||||
- flatpak_bwrap_add_args (bwrap, "--ro-bind", src, dest, NULL);
|
||||
+ flatpak_bwrap_add_args_data_fd (bwrap,
|
||||
+ "--ro-bind-fd",
|
||||
+ g_steal_fd (&src_fd),
|
||||
+ dest);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3556,9 +3598,9 @@ flatpak_run_setup_base_argv (FlatpakBwrap *bwrap,
|
||||
NULL);
|
||||
}
|
||||
|
||||
- flatpak_run_setup_usr_links (bwrap, runtime_files, NULL);
|
||||
+ flatpak_run_setup_usr_links (bwrap, runtime_fd, NULL);
|
||||
|
||||
- add_tzdata_args (bwrap, runtime_files);
|
||||
+ add_tzdata_args (bwrap, runtime_fd);
|
||||
|
||||
pers = PER_LINUX;
|
||||
|
||||
@@ -3785,7 +3827,7 @@ regenerate_ld_cache (GPtrArray *base_argv_array,
|
||||
GArray *base_fd_array,
|
||||
GFile *app_id_dir,
|
||||
const char *checksum,
|
||||
- GFile *runtime_files,
|
||||
+ int runtime_fd,
|
||||
gboolean generate_ld_so_conf,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
@@ -3825,7 +3867,7 @@ regenerate_ld_cache (GPtrArray *base_argv_array,
|
||||
|
||||
flatpak_bwrap_append_args (bwrap, base_argv_array);
|
||||
|
||||
- flatpak_run_setup_usr_links (bwrap, runtime_files, NULL);
|
||||
+ flatpak_run_setup_usr_links (bwrap, runtime_fd, NULL);
|
||||
|
||||
if (generate_ld_so_conf)
|
||||
{
|
||||
@@ -4048,15 +4090,51 @@ check_sudo (GError **error)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
+static char *
|
||||
+get_path_for_fd (int fd,
|
||||
+ GError **error)
|
||||
+{
|
||||
+ g_autofree char *proc_path = NULL;
|
||||
+ g_autofree char *path = NULL;
|
||||
+
|
||||
+ proc_path = g_strdup_printf ("/proc/self/fd/%d", fd);
|
||||
+ path = glnx_readlinkat_malloc (AT_FDCWD, proc_path, NULL, error);
|
||||
+ if (path == NULL)
|
||||
+ return NULL;
|
||||
+
|
||||
+ /* All normal paths start with /, but some weird things
|
||||
+ don't, such as socket:[27345] or anon_inode:[eventfd].
|
||||
+ We don't support any of these */
|
||||
+ if (path[0] != '/')
|
||||
+ {
|
||||
+ return glnx_null_throw (error, "%s resolves to non-absolute path %s",
|
||||
+ proc_path, path);
|
||||
+ }
|
||||
+
|
||||
+ /* File descriptors to actually deleted files have " (deleted)"
|
||||
+ appended to them. This also happens to some fake fd types
|
||||
+ like shmem which are "/<name> (deleted)". All such
|
||||
+ files are considered invalid. Unfortunately this also
|
||||
+ matches files with filenames that actually end in " (deleted)",
|
||||
+ but there is not much to do about this. */
|
||||
+ if (g_str_has_suffix (path, " (deleted)"))
|
||||
+ {
|
||||
+ return glnx_null_throw (error, "%s resolves to deleted path %s",
|
||||
+ proc_path, path);
|
||||
+ }
|
||||
+
|
||||
+ return g_steal_pointer (&path);
|
||||
+}
|
||||
+
|
||||
gboolean
|
||||
flatpak_run_app (FlatpakDecomposed *app_ref,
|
||||
FlatpakDeploy *app_deploy,
|
||||
- const char *custom_app_path,
|
||||
+ int custom_app_fd,
|
||||
FlatpakContext *extra_context,
|
||||
const char *custom_runtime,
|
||||
const char *custom_runtime_version,
|
||||
const char *custom_runtime_commit,
|
||||
- const char *custom_usr_path,
|
||||
+ int custom_runtime_fd,
|
||||
int parent_pid,
|
||||
FlatpakRunFlags flags,
|
||||
const char *cwd,
|
||||
@@ -4071,11 +4149,6 @@ flatpak_run_app (FlatpakDecomposed *app_ref,
|
||||
g_autoptr(FlatpakDeploy) runtime_deploy = NULL;
|
||||
g_autoptr(GBytes) runtime_deploy_data = NULL;
|
||||
g_autoptr(GBytes) app_deploy_data = NULL;
|
||||
- g_autoptr(GFile) app_files = NULL;
|
||||
- g_autoptr(GFile) original_app_files = NULL;
|
||||
- g_autoptr(GFile) runtime_files = NULL;
|
||||
- g_autoptr(GFile) original_runtime_files = NULL;
|
||||
- g_autoptr(GFile) bin_ldconfig = NULL;
|
||||
g_autoptr(GFile) app_id_dir = NULL;
|
||||
g_autoptr(GFile) real_app_id_dir = NULL;
|
||||
g_autofree char *default_runtime_pref = NULL;
|
||||
@@ -4107,18 +4180,39 @@ flatpak_run_app (FlatpakDecomposed *app_ref,
|
||||
g_autofree char *per_app_dir_lock_path = NULL;
|
||||
g_autofree char *shared_xdg_runtime_dir = NULL;
|
||||
int ld_so_fd = -1;
|
||||
- g_autoptr(GFile) runtime_ld_so_conf = NULL;
|
||||
gboolean generate_ld_so_conf = TRUE;
|
||||
gboolean use_ld_so_cache = TRUE;
|
||||
gboolean sandboxed = (flags & FLATPAK_RUN_FLAG_SANDBOX) != 0;
|
||||
gboolean parent_expose_pids = (flags & FLATPAK_RUN_FLAG_PARENT_EXPOSE_PIDS) != 0;
|
||||
gboolean parent_share_pids = (flags & FLATPAK_RUN_FLAG_PARENT_SHARE_PIDS) != 0;
|
||||
- const char *app_target_path = "/app";
|
||||
- const char *runtime_target_path = "/usr";
|
||||
- struct stat s;
|
||||
+ glnx_autofd int original_runtime_fd = -1;
|
||||
+ g_autoptr(GFile) original_runtime_files = NULL;
|
||||
+ g_autoptr(GFile) custom_runtime_files = NULL;
|
||||
+ /* borrows from either original_runtime_fd or custom_runtime_fd */
|
||||
+ int runtime_fd = -1;
|
||||
+ /* borrows from either original_runtime_files or custom_runtime_files */
|
||||
+ GFile *runtime_files = NULL;
|
||||
+ const char *original_runtime_target_path = NULL;
|
||||
+ glnx_autofd int original_app_fd = -1;
|
||||
+ g_autoptr(GFile) original_app_files = NULL;
|
||||
+ g_autoptr(GFile) custom_app_files = NULL;
|
||||
+ /* borrows from either original_app_fd or custom_app_fd */
|
||||
+ int app_fd = -1;
|
||||
+ /* borrows from either original_app_files or custom_app_files */
|
||||
+ GFile *app_files = NULL;
|
||||
+ const char *original_app_target_path = NULL;
|
||||
|
||||
g_return_val_if_fail (app_ref != NULL, FALSE);
|
||||
|
||||
+ g_return_val_if_fail (custom_app_fd == FLATPAK_RUN_APP_DEPLOY_APP_ORIGINAL ||
|
||||
+ custom_app_fd == FLATPAK_RUN_APP_DEPLOY_APP_EMPTY ||
|
||||
+ custom_app_fd >= 0,
|
||||
+ FALSE);
|
||||
+
|
||||
+ g_return_val_if_fail (custom_runtime_fd == FLATPAK_RUN_APP_DEPLOY_USR_ORIGINAL ||
|
||||
+ custom_runtime_fd >= 0,
|
||||
+ FALSE);
|
||||
+
|
||||
if (!check_sudo (error))
|
||||
return FALSE;
|
||||
|
||||
@@ -4231,38 +4325,53 @@ flatpak_run_app (FlatpakDecomposed *app_ref,
|
||||
flatpak_context_merge (app_context, extra_context);
|
||||
|
||||
original_runtime_files = flatpak_deploy_get_files (runtime_deploy);
|
||||
+ original_runtime_fd = open (flatpak_file_get_path_cached (original_runtime_files),
|
||||
+ O_PATH | O_CLOEXEC);
|
||||
+ if (original_runtime_fd < 0)
|
||||
+ return glnx_throw_errno_prefix (error, "Failed to open original runtime");
|
||||
|
||||
- if (custom_usr_path != NULL)
|
||||
+ if (custom_runtime_fd >= 0)
|
||||
{
|
||||
- runtime_files = g_file_new_for_path (custom_usr_path);
|
||||
- /* Mount the original runtime below here instead of /usr */
|
||||
- runtime_target_path = "/run/parent/usr";
|
||||
+ g_autofree char *path = NULL;
|
||||
+
|
||||
+ path = get_path_for_fd (custom_runtime_fd, &my_error);
|
||||
+ if (path == NULL)
|
||||
+ {
|
||||
+ return flatpak_fail_error (error, FLATPAK_ERROR,
|
||||
+ "Cannot convert custom usr fd to path: %s",
|
||||
+ my_error->message);
|
||||
+ }
|
||||
+
|
||||
+ custom_runtime_files = g_file_new_for_path (path);
|
||||
+
|
||||
+ original_runtime_target_path = "/run/parent/usr";
|
||||
+ runtime_fd = custom_runtime_fd;
|
||||
+ runtime_files = custom_runtime_files;
|
||||
+ }
|
||||
+ else if (custom_app_fd == FLATPAK_RUN_APP_DEPLOY_USR_ORIGINAL)
|
||||
+ {
|
||||
+ original_runtime_target_path = "/usr";
|
||||
+ runtime_fd = original_runtime_fd;
|
||||
+ runtime_files = original_runtime_files;
|
||||
}
|
||||
else
|
||||
{
|
||||
- runtime_files = g_object_ref (original_runtime_files);
|
||||
+ g_assert_not_reached ();
|
||||
}
|
||||
|
||||
- bin_ldconfig = g_file_resolve_relative_path (runtime_files, "bin/ldconfig");
|
||||
- if (!g_file_query_exists (bin_ldconfig, NULL))
|
||||
- use_ld_so_cache = FALSE;
|
||||
-
|
||||
- /* We can't use the ld.so cache if we are using a custom /usr or /app,
|
||||
- * because we don't have a unique ID for the /usr or /app, so we can't
|
||||
- * do cache-invalidation correctly. The caller can either build their
|
||||
- * own ld.so.cache before supplying us with the runtime, or supply
|
||||
- * their own LD_LIBRARY_PATH. */
|
||||
- if (custom_usr_path != NULL || custom_app_path != NULL)
|
||||
- use_ld_so_cache = FALSE;
|
||||
-
|
||||
if (app_deploy != NULL)
|
||||
{
|
||||
g_autofree const char **previous_ids = NULL;
|
||||
gsize len = 0;
|
||||
gboolean do_migrate;
|
||||
|
||||
- real_app_id_dir = flatpak_get_data_dir (app_id);
|
||||
original_app_files = flatpak_deploy_get_files (app_deploy);
|
||||
+ original_app_fd = open (flatpak_file_get_path_cached (original_app_files),
|
||||
+ O_PATH | O_CLOEXEC | O_NOFOLLOW);
|
||||
+ if (original_app_fd < 0)
|
||||
+ return glnx_throw_errno_prefix (error, "Failed to open original runtime");
|
||||
+
|
||||
+ real_app_id_dir = flatpak_get_data_dir (app_id);
|
||||
|
||||
previous_app_id_dirs = g_ptr_array_new_with_free_func (g_object_unref);
|
||||
previous_ids = flatpak_deploy_data_get_previous_ids (app_deploy_data, &len);
|
||||
@@ -4343,19 +4452,60 @@ flatpak_run_app (FlatpakDecomposed *app_ref,
|
||||
app_id_dir = g_object_ref (real_app_id_dir);
|
||||
}
|
||||
|
||||
- if (custom_app_path != NULL)
|
||||
+ if (custom_app_fd >= 0)
|
||||
{
|
||||
- if (strcmp (custom_app_path, "") == 0)
|
||||
- app_files = NULL;
|
||||
- else
|
||||
- app_files = g_file_new_for_path (custom_app_path);
|
||||
+ g_autofree char *path = NULL;
|
||||
|
||||
- /* Mount the original app below here */
|
||||
- app_target_path = "/run/parent/app";
|
||||
+ path = get_path_for_fd (custom_app_fd, error);
|
||||
+ if (path == NULL)
|
||||
+ return glnx_prefix_error (error, "Cannot convert custom app fd to path");
|
||||
+
|
||||
+ custom_app_files = g_file_new_for_path (path);
|
||||
+
|
||||
+ original_app_target_path = "/run/parent/app";
|
||||
+ app_fd = custom_app_fd;
|
||||
+ app_files = custom_app_files;
|
||||
+ }
|
||||
+ else if (custom_app_fd == FLATPAK_RUN_APP_DEPLOY_APP_ORIGINAL)
|
||||
+ {
|
||||
+ original_app_target_path = "/app";
|
||||
+ app_fd = original_app_fd;
|
||||
+ app_files = original_app_files;
|
||||
+ }
|
||||
+ else if (custom_app_fd == FLATPAK_RUN_APP_DEPLOY_APP_EMPTY)
|
||||
+ {
|
||||
+ app_fd = -1;
|
||||
+ app_files = NULL;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ g_assert_not_reached ();
|
||||
}
|
||||
- else if (original_app_files != NULL)
|
||||
+
|
||||
+ /* We can't use the ld.so cache if we are using a custom /usr or /app,
|
||||
+ * because we don't have a unique ID for the /usr or /app, so we can't
|
||||
+ * do cache-invalidation correctly. The caller can either build their
|
||||
+ * own ld.so.cache before supplying us with the runtime, or supply
|
||||
+ * their own LD_LIBRARY_PATH. */
|
||||
+ if (runtime_fd == custom_runtime_fd || app_fd == custom_app_fd)
|
||||
{
|
||||
- app_files = g_object_ref (original_app_files);
|
||||
+ use_ld_so_cache = FALSE;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ glnx_autofd int ldconfig_fd = -1;
|
||||
+
|
||||
+ ldconfig_fd = glnx_chaseat (runtime_fd, "bin/ldconfig",
|
||||
+ GLNX_CHASE_RESOLVE_BENEATH |
|
||||
+ GLNX_CHASE_MUST_BE_REGULAR,
|
||||
+ &my_error);
|
||||
+ if (ldconfig_fd < 0)
|
||||
+ {
|
||||
+ use_ld_so_cache = FALSE;
|
||||
+ g_debug ("bin/ldconfig not found in runtime: %s", my_error->message);
|
||||
+ }
|
||||
+
|
||||
+ g_clear_error (&my_error);
|
||||
}
|
||||
|
||||
flatpak_run_apply_env_default (bwrap, use_ld_so_cache);
|
||||
@@ -4368,75 +4518,86 @@ flatpak_run_app (FlatpakDecomposed *app_ref,
|
||||
flatpak_bwrap_set_env (bwrap, "FLATPAK_SANDBOX_DIR", flatpak_file_get_path_cached (sandbox_dir), TRUE);
|
||||
}
|
||||
|
||||
- flatpak_bwrap_add_args (bwrap,
|
||||
- "--ro-bind", flatpak_file_get_path_cached (runtime_files), "/usr",
|
||||
- NULL);
|
||||
-
|
||||
- if (runtime_files == original_runtime_files)
|
||||
- {
|
||||
- /* All true Flatpak runtimes have files/.ref */
|
||||
- flatpak_bwrap_add_args (bwrap,
|
||||
- "--lock-file", "/usr/.ref",
|
||||
- NULL);
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- g_autoptr(GFile) runtime_child = NULL;
|
||||
+ if (!flatpak_bwrap_add_args_data_fd_dup (bwrap,
|
||||
+ "--ro-bind-fd", runtime_fd, "/usr",
|
||||
+ error))
|
||||
+ return FALSE;
|
||||
|
||||
- runtime_child = g_file_get_child (runtime_files, ".ref");
|
||||
+ {
|
||||
+ glnx_autofd int runtime_ref_fd = -1;
|
||||
|
||||
- /* Lock ${usr}/.ref if it exists */
|
||||
- if (g_file_query_exists (runtime_child, NULL))
|
||||
+ runtime_ref_fd = glnx_chaseat (runtime_fd, ".ref",
|
||||
+ GLNX_CHASE_RESOLVE_BENEATH |
|
||||
+ GLNX_CHASE_MUST_BE_REGULAR,
|
||||
+ NULL);
|
||||
+ if (runtime_ref_fd >= 0)
|
||||
+ {
|
||||
flatpak_bwrap_add_args (bwrap,
|
||||
"--lock-file", "/usr/.ref",
|
||||
NULL);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (runtime_fd == custom_runtime_fd)
|
||||
+ {
|
||||
+ glnx_autofd int original_runtime_ref_fd = -1;
|
||||
+ glnx_autofd int original_runtime_etc_fd = -1;
|
||||
|
||||
/* Put the real Flatpak runtime in /run/parent, so that the
|
||||
* replacement /usr can have symlinks into /run/parent in order
|
||||
* to use the Flatpak runtime's graphics drivers etc. if desired */
|
||||
- flatpak_bwrap_add_args (bwrap,
|
||||
- "--ro-bind",
|
||||
- flatpak_file_get_path_cached (original_runtime_files),
|
||||
- "/run/parent/usr",
|
||||
- "--lock-file", "/run/parent/usr/.ref",
|
||||
- NULL);
|
||||
- flatpak_run_setup_usr_links (bwrap, original_runtime_files,
|
||||
- "/run/parent");
|
||||
+ if (!flatpak_bwrap_add_args_data_fd_dup (bwrap,
|
||||
+ "--ro-bind-fd",
|
||||
+ original_runtime_fd,
|
||||
+ "/run/parent/usr",
|
||||
+ error))
|
||||
+ return FALSE;
|
||||
|
||||
- g_clear_object (&runtime_child);
|
||||
- runtime_child = g_file_get_child (original_runtime_files, "etc");
|
||||
+ original_runtime_ref_fd = glnx_chaseat (original_runtime_fd, ".ref",
|
||||
+ GLNX_CHASE_RESOLVE_BENEATH |
|
||||
+ GLNX_CHASE_MUST_BE_REGULAR,
|
||||
+ NULL);
|
||||
+ if (original_runtime_ref_fd >= 0)
|
||||
+ {
|
||||
+ flatpak_bwrap_add_args (bwrap,
|
||||
+ "--lock-file", "/run/parent/usr/.ref",
|
||||
+ NULL);
|
||||
+ }
|
||||
|
||||
- if (g_file_query_exists (runtime_child, NULL))
|
||||
- flatpak_bwrap_add_args (bwrap,
|
||||
- "--symlink", "usr/etc", "/run/parent/etc",
|
||||
- NULL);
|
||||
+ original_runtime_etc_fd = glnx_chaseat (original_runtime_fd, "etc",
|
||||
+ GLNX_CHASE_RESOLVE_BENEATH |
|
||||
+ GLNX_CHASE_MUST_BE_REGULAR,
|
||||
+ NULL);
|
||||
+ if (original_runtime_etc_fd >= 0)
|
||||
+ {
|
||||
+ flatpak_bwrap_add_args (bwrap,
|
||||
+ "--symlink", "usr/etc", "/run/parent/etc",
|
||||
+ NULL);
|
||||
+ }
|
||||
+
|
||||
+ flatpak_run_setup_usr_links (bwrap, original_runtime_fd,
|
||||
+ "/run/parent");
|
||||
}
|
||||
|
||||
- if (app_files != NULL)
|
||||
+ if (app_fd >= 0)
|
||||
{
|
||||
- flatpak_bwrap_add_args (bwrap,
|
||||
- "--ro-bind", flatpak_file_get_path_cached (app_files), "/app",
|
||||
- NULL);
|
||||
+ glnx_autofd int app_ref_fd = -1;
|
||||
|
||||
- if (app_files == original_app_files)
|
||||
+ if (!flatpak_bwrap_add_args_data_fd_dup (bwrap,
|
||||
+ "--ro-bind-fd", app_fd, "/app",
|
||||
+ error))
|
||||
+ return FALSE;
|
||||
+
|
||||
+ app_ref_fd = glnx_chaseat (app_fd, ".ref",
|
||||
+ GLNX_CHASE_RESOLVE_BENEATH |
|
||||
+ GLNX_CHASE_MUST_BE_REGULAR,
|
||||
+ NULL);
|
||||
+ if (app_ref_fd >= 0)
|
||||
{
|
||||
- /* All true Flatpak apps have files/.ref */
|
||||
flatpak_bwrap_add_args (bwrap,
|
||||
"--lock-file", "/app/.ref",
|
||||
NULL);
|
||||
}
|
||||
- else
|
||||
- {
|
||||
- g_autoptr(GFile) app_child = NULL;
|
||||
-
|
||||
- app_child = g_file_get_child (app_files, ".ref");
|
||||
-
|
||||
- /* Lock ${app}/.ref if it exists */
|
||||
- if (g_file_query_exists (app_child, NULL))
|
||||
- flatpak_bwrap_add_args (bwrap,
|
||||
- "--lock-file", "/app/.ref",
|
||||
- NULL);
|
||||
- }
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -4445,7 +4606,7 @@ flatpak_run_app (FlatpakDecomposed *app_ref,
|
||||
NULL);
|
||||
}
|
||||
|
||||
- if (original_app_files != NULL && app_files != original_app_files)
|
||||
+ if (original_app_fd >= 0 && original_app_fd != app_fd)
|
||||
{
|
||||
/* Put the real Flatpak app in /run/parent/app */
|
||||
flatpak_bwrap_add_args (bwrap,
|
||||
@@ -4458,26 +4619,37 @@ flatpak_run_app (FlatpakDecomposed *app_ref,
|
||||
|
||||
if (metakey != NULL &&
|
||||
!flatpak_run_add_extension_args (bwrap, metakey, app_ref,
|
||||
- use_ld_so_cache, app_target_path,
|
||||
+ use_ld_so_cache, original_app_target_path,
|
||||
&app_extensions, &app_ld_path,
|
||||
cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
if (!flatpak_run_add_extension_args (bwrap, runtime_metakey, runtime_ref,
|
||||
- use_ld_so_cache, runtime_target_path,
|
||||
+ use_ld_so_cache, original_runtime_target_path,
|
||||
&runtime_extensions, &runtime_ld_path,
|
||||
cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
- if (custom_usr_path == NULL)
|
||||
+ if (runtime_fd == original_runtime_fd)
|
||||
flatpak_run_extend_ld_path (bwrap, NULL, runtime_ld_path);
|
||||
|
||||
- if (custom_app_path == NULL)
|
||||
+ if (app_fd == original_app_fd)
|
||||
flatpak_run_extend_ld_path (bwrap, app_ld_path, NULL);
|
||||
|
||||
- runtime_ld_so_conf = g_file_resolve_relative_path (runtime_files, "etc/ld.so.conf");
|
||||
- if (lstat (flatpak_file_get_path_cached (runtime_ld_so_conf), &s) == 0)
|
||||
- generate_ld_so_conf = S_ISREG (s.st_mode) && s.st_size == 0;
|
||||
+ {
|
||||
+ glnx_autofd int ld_so_conf_fd = -1;
|
||||
+ struct glnx_statx stx;
|
||||
+
|
||||
+ ld_so_conf_fd = glnx_chase_and_statxat (runtime_fd, "etc/ld.so.conf",
|
||||
+ GLNX_CHASE_RESOLVE_BENEATH |
|
||||
+ GLNX_CHASE_MUST_BE_REGULAR,
|
||||
+ GLNX_STATX_SIZE,
|
||||
+ &stx, NULL);
|
||||
+ if (ld_so_conf_fd < 0 ||
|
||||
+ !(stx.stx_mask & GLNX_STATX_SIZE) ||
|
||||
+ stx.stx_size != 0)
|
||||
+ generate_ld_so_conf = FALSE;
|
||||
+ }
|
||||
|
||||
/* At this point we have the minimal argv set up, with just the app, runtime and extensions.
|
||||
We can reuse this to generate the ld.so.cache (if needed) */
|
||||
@@ -4489,7 +4661,7 @@ flatpak_run_app (FlatpakDecomposed *app_ref,
|
||||
bwrap->fds,
|
||||
app_id_dir,
|
||||
checksum,
|
||||
- runtime_files,
|
||||
+ runtime_fd,
|
||||
generate_ld_so_conf,
|
||||
cancellable, error);
|
||||
if (ld_so_fd == -1)
|
||||
@@ -4499,7 +4671,7 @@ flatpak_run_app (FlatpakDecomposed *app_ref,
|
||||
|
||||
flags |= flatpak_context_get_run_flags (app_context);
|
||||
|
||||
- if (!flatpak_run_setup_base_argv (bwrap, runtime_files, app_id_dir, app_arch, flags, error))
|
||||
+ if (!flatpak_run_setup_base_argv (bwrap, runtime_fd, app_id_dir, app_arch, flags, error))
|
||||
return FALSE;
|
||||
|
||||
if (generate_ld_so_conf)
|
||||
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,78 @@
|
||||
From 7140fee959d82d1c5913167398e6d559f3a13ee3 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Wick <sebastian.wick@redhat.com>
|
||||
Date: Fri, 6 Feb 2026 20:55:46 +0100
|
||||
Subject: [PATCH] run: Add --usr-fd and --app-fd options
|
||||
|
||||
Exposes options to pass in a fd for the runtime and app deploy. The
|
||||
flatpak portal will make use of this in a following commit.
|
||||
---
|
||||
app/flatpak-builtins-run.c | 30 ++++++++++++++++++++++++++++--
|
||||
1 file changed, 28 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/app/flatpak-builtins-run.c b/app/flatpak-builtins-run.c
|
||||
index 9403d8ae..a2d71420 100644
|
||||
--- a/app/flatpak-builtins-run.c
|
||||
+++ b/app/flatpak-builtins-run.c
|
||||
@@ -60,7 +60,9 @@ static gboolean opt_parent_expose_pids;
|
||||
static gboolean opt_parent_share_pids;
|
||||
static int opt_instance_id_fd = -1;
|
||||
static char *opt_app_path;
|
||||
+static int opt_app_fd = -1;
|
||||
static char *opt_usr_path;
|
||||
+static int opt_usr_fd = -1;
|
||||
|
||||
static GOptionEntry options[] = {
|
||||
{ "arch", 0, 0, G_OPTION_ARG_STRING, &opt_arch, N_("Arch to use"), N_("ARCH") },
|
||||
@@ -88,7 +90,9 @@ static GOptionEntry options[] = {
|
||||
{ "parent-share-pids", 0, 0, G_OPTION_ARG_NONE, &opt_parent_share_pids, N_("Share process ID namespace with parent"), NULL },
|
||||
{ "instance-id-fd", 0, 0, G_OPTION_ARG_INT, &opt_instance_id_fd, N_("Write the instance ID to the given file descriptor"), NULL },
|
||||
{ "app-path", 0, 0, G_OPTION_ARG_FILENAME, &opt_app_path, N_("Use PATH instead of the app's /app"), N_("PATH") },
|
||||
+ { "app-fd", 0, 0, G_OPTION_ARG_INT, &opt_app_fd, N_("Use FD instead of the app's /app"), N_("FD") },
|
||||
{ "usr-path", 0, 0, G_OPTION_ARG_FILENAME, &opt_usr_path, N_("Use PATH instead of the runtime's /usr"), N_("PATH") },
|
||||
+ { "usr-fd", 0, 0, G_OPTION_ARG_INT, &opt_usr_fd, N_("Use FD instead of the runtime's /usr"), N_("FD") },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
@@ -307,7 +311,18 @@ flatpak_builtin_run (int argc, char **argv, GCancellable *cancellable, GError **
|
||||
if (!opt_session_bus)
|
||||
flags |= FLATPAK_RUN_FLAG_NO_SESSION_BUS_PROXY;
|
||||
|
||||
- if (opt_app_path != NULL)
|
||||
+ if (opt_app_fd >= 0 && opt_app_path != NULL)
|
||||
+ {
|
||||
+ flatpak_fail_error (error, FLATPAK_ERROR,
|
||||
+ _("app-fd and app-path cannot both be used"));
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
+ if (opt_app_fd >= 0)
|
||||
+ {
|
||||
+ app_fd = opt_app_fd;
|
||||
+ }
|
||||
+ else if (opt_app_path != NULL)
|
||||
{
|
||||
if (g_strcmp0 (opt_app_path, "") == 0)
|
||||
{
|
||||
@@ -326,7 +341,18 @@ flatpak_builtin_run (int argc, char **argv, GCancellable *cancellable, GError **
|
||||
app_fd = FLATPAK_RUN_APP_DEPLOY_APP_ORIGINAL;
|
||||
}
|
||||
|
||||
- if (opt_usr_path != NULL)
|
||||
+ if (opt_usr_fd >= 0 && opt_usr_path != NULL)
|
||||
+ {
|
||||
+ flatpak_fail_error (error, FLATPAK_ERROR,
|
||||
+ _("usr-fd and usr-path cannot both be used"));
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
+ if (opt_usr_fd >= 0)
|
||||
+ {
|
||||
+ usr_fd = opt_usr_fd;
|
||||
+ }
|
||||
+ else if (opt_usr_path != NULL)
|
||||
{
|
||||
usr_fd = open (opt_usr_path, O_PATH | O_CLOEXEC | O_NOFOLLOW);
|
||||
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,116 @@
|
||||
From 3a55408e13066f39f78158d3026ea3581f0b28c6 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Wick <sebastian.wick@redhat.com>
|
||||
Date: Fri, 6 Feb 2026 21:02:47 +0100
|
||||
Subject: [PATCH] run: Add (ro-)bind fds to flatpak_run_app
|
||||
|
||||
The flatpak portal allows apps to expose files and folders from within
|
||||
the sandbox to a side-sandbox using flatpak-spawn. So far it has used
|
||||
the --filesystem option to mount those files and folders, but it takes a
|
||||
path. Paths are inherently racy and they allow the app to swap out any
|
||||
component of the path with a symlink after handing it off. If they win
|
||||
the race, flatpak will mount a completely different directory.
|
||||
|
||||
This adds a new way to mount files and directories based on O_PATH
|
||||
file descriptor that needs to provided when execing the flatpak binary.
|
||||
---
|
||||
app/flatpak-builtins-run.c | 2 ++
|
||||
common/flatpak-installation.c | 1 +
|
||||
common/flatpak-run-private.h | 2 ++
|
||||
common/flatpak-run.c | 36 +++++++++++++++++++++++++++++++++++
|
||||
4 files changed, 41 insertions(+)
|
||||
|
||||
diff --git a/app/flatpak-builtins-run.c b/app/flatpak-builtins-run.c
|
||||
index a2d71420..7190f1f7 100644
|
||||
--- a/app/flatpak-builtins-run.c
|
||||
+++ b/app/flatpak-builtins-run.c
|
||||
@@ -380,6 +380,8 @@ flatpak_builtin_run (int argc, char **argv, GCancellable *cancellable, GError **
|
||||
rest_argc - 1,
|
||||
opt_instance_id_fd,
|
||||
NULL,
|
||||
+ NULL,
|
||||
+ NULL,
|
||||
cancellable,
|
||||
error))
|
||||
return FALSE;
|
||||
diff --git a/common/flatpak-installation.c b/common/flatpak-installation.c
|
||||
index 9254252d..6eb16459 100644
|
||||
--- a/common/flatpak-installation.c
|
||||
+++ b/common/flatpak-installation.c
|
||||
@@ -710,6 +710,7 @@ flatpak_installation_launch_full (FlatpakInstallation *self,
|
||||
NULL,
|
||||
NULL, 0, -1,
|
||||
&instance_dir,
|
||||
+ NULL, NULL,
|
||||
cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
diff --git a/common/flatpak-run-private.h b/common/flatpak-run-private.h
|
||||
index 5fc1f296..23477bd8 100644
|
||||
--- a/common/flatpak-run-private.h
|
||||
+++ b/common/flatpak-run-private.h
|
||||
@@ -200,6 +200,8 @@ gboolean flatpak_run_app (FlatpakDecomposed *app_ref,
|
||||
int n_args,
|
||||
int instance_id_fd,
|
||||
char **instance_dir_out,
|
||||
+ GArray *bind_fds,
|
||||
+ GArray *ro_bind_fds,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
diff --git a/common/flatpak-run.c b/common/flatpak-run.c
|
||||
index 0e1d16f9..9087be23 100644
|
||||
--- a/common/flatpak-run.c
|
||||
+++ b/common/flatpak-run.c
|
||||
@@ -4143,6 +4143,8 @@ flatpak_run_app (FlatpakDecomposed *app_ref,
|
||||
int n_args,
|
||||
int instance_id_fd,
|
||||
char **instance_dir_out,
|
||||
+ GArray *bind_fds,
|
||||
+ GArray *ro_bind_fds,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
@@ -4717,6 +4719,40 @@ flatpak_run_app (FlatpakDecomposed *app_ref,
|
||||
flatpak_bwrap_add_arg_printf (bwrap, "/run/user/%d", getuid ());
|
||||
}
|
||||
|
||||
+ for (i = 0; bind_fds && i < bind_fds->len; i++)
|
||||
+ {
|
||||
+ int fd = g_array_index (bind_fds, int, i);
|
||||
+ g_autofree char *path = NULL;
|
||||
+
|
||||
+ /* We get the path the fd refers to, to determine to mount point
|
||||
+ * destination inside the sandbox */
|
||||
+ path = get_path_for_fd (fd, error);
|
||||
+ if (!path)
|
||||
+ return FALSE;
|
||||
+
|
||||
+ if (!flatpak_bwrap_add_args_data_fd_dup (bwrap,
|
||||
+ "--bind-fd", fd, path,
|
||||
+ error))
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; ro_bind_fds && i < ro_bind_fds->len; i++)
|
||||
+ {
|
||||
+ int fd = g_array_index (ro_bind_fds, int, i);
|
||||
+ g_autofree char *path = NULL;
|
||||
+
|
||||
+ /* We get the path the fd refers to, to determine to mount point
|
||||
+ * destination inside the sandbox */
|
||||
+ path = get_path_for_fd (fd, error);
|
||||
+ if (!path)
|
||||
+ return FALSE;
|
||||
+
|
||||
+ if (!flatpak_bwrap_add_args_data_fd_dup (bwrap,
|
||||
+ "--ro-bind-fd", fd, path,
|
||||
+ error))
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
if (!flatpak_run_add_dconf_args (bwrap, app_id, metakey, error))
|
||||
return FALSE;
|
||||
|
||||
--
|
||||
2.54.0
|
||||
|
||||
95
SOURCES/CVE-2026-34078-7-run-add-ro-bind-fd-options.patch
Normal file
95
SOURCES/CVE-2026-34078-7-run-add-ro-bind-fd-options.patch
Normal file
@ -0,0 +1,95 @@
|
||||
From 9ca818511d96dadbdb7b8deee1f8ef99f10914e6 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Wick <sebastian.wick@redhat.com>
|
||||
Date: Fri, 6 Feb 2026 21:03:34 +0100
|
||||
Subject: [PATCH] run: Add --(ro-)bind-fd options
|
||||
|
||||
Exposes the functionality added to flatpak_run_app in the previous
|
||||
commit with two new options.
|
||||
---
|
||||
app/flatpak-builtins-run.c | 49 ++++++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 47 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/app/flatpak-builtins-run.c b/app/flatpak-builtins-run.c
|
||||
index 7190f1f7..7edd7326 100644
|
||||
--- a/app/flatpak-builtins-run.c
|
||||
+++ b/app/flatpak-builtins-run.c
|
||||
@@ -63,6 +63,46 @@ static char *opt_app_path;
|
||||
static int opt_app_fd = -1;
|
||||
static char *opt_usr_path;
|
||||
static int opt_usr_fd = -1;
|
||||
+static GArray *opt_bind_fds = NULL;
|
||||
+static GArray *opt_ro_bind_fds = NULL;
|
||||
+
|
||||
+static gboolean
|
||||
+option_bind_fd_cb (const char *option_name,
|
||||
+ const char *value,
|
||||
+ gpointer data,
|
||||
+ GError **error)
|
||||
+{
|
||||
+ glnx_autofd int fd = -1;
|
||||
+
|
||||
+ fd = flatpak_parse_fd (value, error);
|
||||
+ if (fd < 0)
|
||||
+ return FALSE;
|
||||
+
|
||||
+ if (fd < 3)
|
||||
+ return glnx_throw (error, "File descriptors 0, 1, 2 are reserved");
|
||||
+
|
||||
+ g_array_append_val (opt_bind_fds, fd);
|
||||
+ return TRUE;
|
||||
+}
|
||||
+
|
||||
+static gboolean
|
||||
+option_ro_bind_fd_cb (const char *option_name,
|
||||
+ const char *value,
|
||||
+ gpointer data,
|
||||
+ GError **error)
|
||||
+{
|
||||
+ glnx_autofd int fd = -1;
|
||||
+
|
||||
+ fd = flatpak_parse_fd (value, error);
|
||||
+ if (fd < 0)
|
||||
+ return FALSE;
|
||||
+
|
||||
+ if (fd < 3)
|
||||
+ return glnx_throw (error, "File descriptors 0, 1, 2 are reserved");
|
||||
+
|
||||
+ g_array_append_val (opt_ro_bind_fds, fd);
|
||||
+ return TRUE;
|
||||
+}
|
||||
|
||||
static GOptionEntry options[] = {
|
||||
{ "arch", 0, 0, G_OPTION_ARG_STRING, &opt_arch, N_("Arch to use"), N_("ARCH") },
|
||||
@@ -93,6 +133,8 @@ static GOptionEntry options[] = {
|
||||
{ "app-fd", 0, 0, G_OPTION_ARG_INT, &opt_app_fd, N_("Use FD instead of the app's /app"), N_("FD") },
|
||||
{ "usr-path", 0, 0, G_OPTION_ARG_FILENAME, &opt_usr_path, N_("Use PATH instead of the runtime's /usr"), N_("PATH") },
|
||||
{ "usr-fd", 0, 0, G_OPTION_ARG_INT, &opt_usr_fd, N_("Use FD instead of the runtime's /usr"), N_("FD") },
|
||||
+ { "bind-fd", 0, 0, G_OPTION_ARG_CALLBACK | G_OPTION_FLAG_HIDDEN, &option_bind_fd_cb, N_("Bind mount the file or directory referred to by FD to its canonicalized path"), N_("FD") },
|
||||
+ { "ro-bind-fd", 0, 0, G_OPTION_ARG_CALLBACK | G_OPTION_FLAG_HIDDEN, &option_ro_bind_fd_cb, N_("Bind mount the file or directory referred to by FD read-only to its canonicalized path"), N_("FD") },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
@@ -117,6 +159,9 @@ flatpak_builtin_run (int argc, char **argv, GCancellable *cancellable, GError **
|
||||
glnx_autofd int app_fd = -1;
|
||||
glnx_autofd int usr_fd = -1;
|
||||
|
||||
+ opt_bind_fds = g_array_new (FALSE, FALSE, sizeof (int));
|
||||
+ opt_ro_bind_fds = g_array_new (FALSE, FALSE, sizeof (int));
|
||||
+
|
||||
context = g_option_context_new (_("APP [ARGUMENT…] - Run an app"));
|
||||
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
|
||||
|
||||
@@ -380,8 +425,8 @@ flatpak_builtin_run (int argc, char **argv, GCancellable *cancellable, GError **
|
||||
rest_argc - 1,
|
||||
opt_instance_id_fd,
|
||||
NULL,
|
||||
- NULL,
|
||||
- NULL,
|
||||
+ opt_bind_fds,
|
||||
+ opt_ro_bind_fds,
|
||||
cancellable,
|
||||
error))
|
||||
return FALSE;
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,601 @@
|
||||
From 9958b547bea1e9335cb91af61a239d1a7039387e Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Wick <sebastian.wick@redhat.com>
|
||||
Date: Fri, 6 Feb 2026 21:03:58 +0100
|
||||
Subject: [PATCH] portal: Use --bind-fd, --app-fd and --usr-fd options to avoid
|
||||
races
|
||||
|
||||
Now that flatpak_run_app accepts fds for app and runtime deploy, as well
|
||||
as bind and ro-bind fds, and flatpak-run exposes the functionality, we
|
||||
can finally hook this all up to the flatpak portal!
|
||||
---
|
||||
portal/flatpak-portal.c | 438 +++++++++++++++-------------------------
|
||||
1 file changed, 162 insertions(+), 276 deletions(-)
|
||||
|
||||
diff --git a/portal/flatpak-portal.c b/portal/flatpak-portal.c
|
||||
index e5701895..a4378f77 100644
|
||||
--- a/portal/flatpak-portal.c
|
||||
+++ b/portal/flatpak-portal.c
|
||||
@@ -550,195 +550,60 @@ child_setup_func (gpointer user_data)
|
||||
}
|
||||
|
||||
static gboolean
|
||||
-is_valid_expose (const char *expose,
|
||||
- GError **error)
|
||||
+validate_opath_fd (int fd,
|
||||
+ gboolean needs_writable,
|
||||
+ GError **error)
|
||||
{
|
||||
- /* No subdirs or absolute paths */
|
||||
- if (expose[0] == '/')
|
||||
- {
|
||||
- g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
|
||||
- "Invalid sandbox expose: absolute paths not allowed");
|
||||
- return FALSE;
|
||||
- }
|
||||
- else if (strchr (expose, '/'))
|
||||
- {
|
||||
- g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
|
||||
- "Invalid sandbox expose: subdirectories not allowed");
|
||||
- return FALSE;
|
||||
- }
|
||||
-
|
||||
- return TRUE;
|
||||
-}
|
||||
-
|
||||
-static char *
|
||||
-filesystem_arg (const char *path,
|
||||
- gboolean readonly)
|
||||
-{
|
||||
- g_autoptr(GString) s = g_string_new ("--filesystem=");
|
||||
- const char *p;
|
||||
-
|
||||
- for (p = path; *p != 0; p++)
|
||||
- {
|
||||
- if (*p == ':')
|
||||
- g_string_append (s, "\\:");
|
||||
- else
|
||||
- g_string_append_c (s, *p);
|
||||
- }
|
||||
-
|
||||
- if (readonly)
|
||||
- g_string_append (s, ":ro");
|
||||
-
|
||||
- return g_string_free (g_steal_pointer (&s), FALSE);
|
||||
-}
|
||||
-
|
||||
-
|
||||
-static char *
|
||||
-filesystem_sandbox_arg (const char *path,
|
||||
- const char *sandbox,
|
||||
- gboolean readonly)
|
||||
-{
|
||||
- g_autoptr(GString) s = g_string_new ("--filesystem=");
|
||||
- const char *p;
|
||||
-
|
||||
- for (p = path; *p != 0; p++)
|
||||
- {
|
||||
- if (*p == ':')
|
||||
- g_string_append (s, "\\:");
|
||||
- else
|
||||
- g_string_append_c (s, *p);
|
||||
- }
|
||||
-
|
||||
- g_string_append (s, "/sandbox/");
|
||||
-
|
||||
- for (p = sandbox; *p != 0; p++)
|
||||
- {
|
||||
- if (*p == ':')
|
||||
- g_string_append (s, "\\:");
|
||||
- else
|
||||
- g_string_append_c (s, *p);
|
||||
- }
|
||||
-
|
||||
- if (readonly)
|
||||
- g_string_append (s, ":ro");
|
||||
-
|
||||
- return g_string_free (g_steal_pointer (&s), FALSE);
|
||||
-}
|
||||
-
|
||||
-static char *
|
||||
-bubblewrap_remap_path (const char *path)
|
||||
-{
|
||||
- if (g_str_has_prefix (path, "/newroot/"))
|
||||
- path = path + strlen ("/newroot");
|
||||
- return g_strdup (path);
|
||||
-}
|
||||
-
|
||||
-static char *
|
||||
-verify_proc_self_fd (const char *proc_path,
|
||||
- GError **error)
|
||||
-{
|
||||
- char path_buffer[PATH_MAX + 1];
|
||||
- ssize_t symlink_size;
|
||||
-
|
||||
- symlink_size = readlink (proc_path, path_buffer, PATH_MAX);
|
||||
- if (symlink_size < 0)
|
||||
- return glnx_null_throw_errno_prefix (error, "readlink");
|
||||
-
|
||||
- path_buffer[symlink_size] = 0;
|
||||
-
|
||||
- /* All normal paths start with /, but some weird things
|
||||
- don't, such as socket:[27345] or anon_inode:[eventfd].
|
||||
- We don't support any of these */
|
||||
- if (path_buffer[0] != '/')
|
||||
- return glnx_null_throw (error, "%s resolves to non-absolute path %s",
|
||||
- proc_path, path_buffer);
|
||||
-
|
||||
- /* File descriptors to actually deleted files have " (deleted)"
|
||||
- appended to them. This also happens to some fake fd types
|
||||
- like shmem which are "/<name> (deleted)". All such
|
||||
- files are considered invalid. Unfortunatelly this also
|
||||
- matches files with filenames that actually end in " (deleted)",
|
||||
- but there is not much to do about this. */
|
||||
- if (g_str_has_suffix (path_buffer, " (deleted)"))
|
||||
- return glnx_null_throw (error, "%s resolves to deleted path %s",
|
||||
- proc_path, path_buffer);
|
||||
-
|
||||
- /* remap from sandbox to host if needed */
|
||||
- return bubblewrap_remap_path (path_buffer);
|
||||
-}
|
||||
-
|
||||
-static char *
|
||||
-get_path_for_fd (int fd,
|
||||
- gboolean *writable_out,
|
||||
- GError **error)
|
||||
-{
|
||||
- g_autofree char *proc_path = NULL;
|
||||
int fd_flags;
|
||||
struct stat st_buf;
|
||||
- struct stat real_st_buf;
|
||||
- g_autofree char *path = NULL;
|
||||
- gboolean writable = FALSE;
|
||||
- int read_access_mode;
|
||||
+ int access_mode;
|
||||
|
||||
/* Must be able to get fd flags */
|
||||
fd_flags = fcntl (fd, F_GETFL);
|
||||
- if (fd_flags == -1)
|
||||
- return glnx_null_throw_errno_prefix (error, "fcntl F_GETFL");
|
||||
+ if (fd_flags < 0)
|
||||
+ return glnx_throw_errno_prefix (error, "Failed to get fd flags");
|
||||
|
||||
/* Must be O_PATH */
|
||||
if ((fd_flags & O_PATH) != O_PATH)
|
||||
- return glnx_null_throw (error, "not opened with O_PATH");
|
||||
-
|
||||
- /* We don't want to allow exposing symlinks, because if they are
|
||||
- * under the callers control they could be changed between now and
|
||||
- * starting the child allowing it to point anywhere, so enforce NOFOLLOW.
|
||||
- * and verify that stat is not a link.
|
||||
- */
|
||||
- if ((fd_flags & O_NOFOLLOW) != O_NOFOLLOW)
|
||||
- return glnx_null_throw (error, "not opened with O_NOFOLLOW");
|
||||
+ {
|
||||
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
+ "File descriptor is not O_PATH");
|
||||
+ return FALSE;
|
||||
+ }
|
||||
|
||||
/* Must be able to fstat */
|
||||
if (fstat (fd, &st_buf) < 0)
|
||||
- return glnx_null_throw_errno_prefix (error, "fstat");
|
||||
-
|
||||
- /* As per above, no symlinks */
|
||||
- if (S_ISLNK (st_buf.st_mode))
|
||||
- return glnx_null_throw (error, "is a symbolic link");
|
||||
+ return glnx_throw_errno_prefix (error, "Failed to fstat");
|
||||
|
||||
- proc_path = g_strdup_printf ("/proc/self/fd/%d", fd);
|
||||
-
|
||||
- /* Must be able to read valid path from /proc/self/fd */
|
||||
- /* This is an absolute and (at least at open time) symlink-expanded path */
|
||||
- path = verify_proc_self_fd (proc_path, error);
|
||||
- if (path == NULL)
|
||||
- return NULL;
|
||||
+ access_mode = R_OK;
|
||||
+ if (S_ISDIR (st_buf.st_mode))
|
||||
+ access_mode |= X_OK;
|
||||
|
||||
- /* Verify that this is the same file as the app opened */
|
||||
- if (stat (path, &real_st_buf) < 0 ||
|
||||
- st_buf.st_dev != real_st_buf.st_dev ||
|
||||
- st_buf.st_ino != real_st_buf.st_ino)
|
||||
- {
|
||||
- /* Different files on the inside and the outside, reject the request */
|
||||
- return glnx_null_throw (error,
|
||||
- "different file inside and outside sandbox");
|
||||
- }
|
||||
+ if (needs_writable)
|
||||
+ access_mode |= W_OK;
|
||||
|
||||
- read_access_mode = R_OK;
|
||||
- if (S_ISDIR (st_buf.st_mode))
|
||||
- read_access_mode |= X_OK;
|
||||
+ /* Must be able to access readable and potentially writable */
|
||||
+ if (faccessat (fd, "", access_mode, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW) != 0)
|
||||
+ return glnx_throw_errno_prefix (error, "Bad access mode");
|
||||
|
||||
- /* Must be able to access the path via the sandbox supplied O_PATH fd,
|
||||
- which applies the sandbox side mount options (like readonly). */
|
||||
- if (access (proc_path, read_access_mode) != 0)
|
||||
- return glnx_null_throw (error, "not %s in sandbox",
|
||||
- read_access_mode & X_OK ? "accessible" : "readable");
|
||||
+ return TRUE;
|
||||
+}
|
||||
|
||||
- if (access (proc_path, W_OK) == 0)
|
||||
- writable = TRUE;
|
||||
+static int
|
||||
+fd_map_remap_fd (GArray *fd_map,
|
||||
+ int *max_fd_in_out,
|
||||
+ int fd)
|
||||
+{
|
||||
+ FdMapEntry fd_map_entry;
|
||||
|
||||
- if (writable_out != NULL)
|
||||
- *writable_out = writable;
|
||||
+ /* Use a fd that hasn't been used yet. We might have to reshuffle
|
||||
+ * fd_map_entry.to, a bit later. */
|
||||
+ fd_map_entry.from = fd;
|
||||
+ fd_map_entry.to = ++(*max_fd_in_out);
|
||||
+ fd_map_entry.final = fd_map_entry.to;
|
||||
+ g_array_append_val (fd_map, fd_map_entry);
|
||||
|
||||
- return g_steal_pointer (&path);
|
||||
+ return fd_map_entry.final;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -793,9 +658,12 @@ handle_spawn (PortalFlatpak *object,
|
||||
gboolean devel;
|
||||
gboolean empty_app;
|
||||
g_autoptr(GString) env_string = g_string_new ("");
|
||||
- glnx_autofd int env_fd = -1;
|
||||
const char *flatpak;
|
||||
gboolean testing = FALSE;
|
||||
+ g_autoptr(GArray) owned_fds = NULL;
|
||||
+ g_autoptr(GArray) expose_fds = NULL;
|
||||
+ g_autoptr(GArray) expose_fds_ro = NULL;
|
||||
+ glnx_autofd int instance_sandbox_fd = -1;
|
||||
|
||||
child_setup_data.instance_id_fd = -1;
|
||||
child_setup_data.env_fd = -1;
|
||||
@@ -918,29 +786,6 @@ handle_spawn (PortalFlatpak *object,
|
||||
return G_DBUS_METHOD_INVOCATION_HANDLED;
|
||||
}
|
||||
|
||||
- for (i = 0; sandbox_expose != NULL && sandbox_expose[i] != NULL; i++)
|
||||
- {
|
||||
- const char *expose = sandbox_expose[i];
|
||||
-
|
||||
- g_debug ("exposing %s", expose);
|
||||
- if (!is_valid_expose (expose, &error))
|
||||
- {
|
||||
- g_dbus_method_invocation_return_gerror (invocation, error);
|
||||
- return G_DBUS_METHOD_INVOCATION_HANDLED;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- for (i = 0; sandbox_expose_ro != NULL && sandbox_expose_ro[i] != NULL; i++)
|
||||
- {
|
||||
- const char *expose = sandbox_expose_ro[i];
|
||||
- g_debug ("exposing %s", expose);
|
||||
- if (!is_valid_expose (expose, &error))
|
||||
- {
|
||||
- g_dbus_method_invocation_return_gerror (invocation, error);
|
||||
- return G_DBUS_METHOD_INVOCATION_HANDLED;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
g_debug ("Running spawn command %s", arg_argv[0]);
|
||||
|
||||
n_fds = 0;
|
||||
@@ -1112,10 +957,14 @@ handle_spawn (PortalFlatpak *object,
|
||||
g_string_append_c (env_string, '\0');
|
||||
}
|
||||
|
||||
+ owned_fds = g_array_new (FALSE, FALSE, sizeof (int));
|
||||
+ g_array_set_clear_func (owned_fds, (GDestroyNotify) glnx_close_fd);
|
||||
+
|
||||
if (env_string->len > 0)
|
||||
{
|
||||
- FdMapEntry fd_map_entry;
|
||||
g_auto(GLnxTmpfile) env_tmpf = { 0, };
|
||||
+ int env_fd = -1;
|
||||
+ int remapped_fd;
|
||||
|
||||
if (!flatpak_buffer_to_sealed_memfd_or_tmpfile (&env_tmpf, "environ",
|
||||
env_string->str,
|
||||
@@ -1126,16 +975,12 @@ handle_spawn (PortalFlatpak *object,
|
||||
}
|
||||
|
||||
env_fd = glnx_steal_fd (&env_tmpf.fd);
|
||||
+ g_array_append_val (owned_fds, env_fd);
|
||||
|
||||
- /* Use a fd that hasn't been used yet. We might have to reshuffle
|
||||
- * fd_map_entry.to, a bit later. */
|
||||
- fd_map_entry.from = env_fd;
|
||||
- fd_map_entry.to = ++max_fd;
|
||||
- fd_map_entry.final = fd_map_entry.to;
|
||||
- g_array_append_val (fd_map, fd_map_entry);
|
||||
+ remapped_fd = fd_map_remap_fd (fd_map, &max_fd, env_fd);
|
||||
|
||||
g_ptr_array_add (flatpak_argv,
|
||||
- g_strdup_printf ("--env-fd=%d", fd_map_entry.final));
|
||||
+ g_strdup_printf ("--env-fd=%d", remapped_fd));
|
||||
}
|
||||
|
||||
for (i = 0; unset_env != NULL && unset_env[i] != NULL; i++)
|
||||
@@ -1243,54 +1088,100 @@ handle_spawn (PortalFlatpak *object,
|
||||
else
|
||||
g_ptr_array_add (flatpak_argv, g_strdup ("--unshare=network"));
|
||||
|
||||
+ expose_fds = g_array_new (FALSE, FALSE, sizeof (int));
|
||||
+ expose_fds_ro = g_array_new (FALSE, FALSE, sizeof (int));
|
||||
+
|
||||
+ if (instance_path != NULL)
|
||||
+ {
|
||||
+ glnx_autofd int instance_fd = -1;
|
||||
+
|
||||
+ instance_fd = glnx_chaseat (AT_FDCWD, instance_path,
|
||||
+ GLNX_CHASE_DEFAULT,
|
||||
+ &error);
|
||||
+ if (instance_fd < 0)
|
||||
+ {
|
||||
+ g_dbus_method_invocation_return_gerror (invocation, error);
|
||||
+ return G_DBUS_METHOD_INVOCATION_HANDLED;
|
||||
+ }
|
||||
+
|
||||
+ if (!glnx_ensure_dir (instance_fd, "sandbox", 0700, &error))
|
||||
+ {
|
||||
+ g_warning ("Unable to create %s/sandbox: %s", instance_path, error->message);
|
||||
+ g_clear_error (&error);
|
||||
+ }
|
||||
+
|
||||
+ instance_sandbox_fd = glnx_chaseat (instance_fd, "sandbox",
|
||||
+ GLNX_CHASE_RESOLVE_NO_SYMLINKS,
|
||||
+ &error);
|
||||
+ if (instance_sandbox_fd < 0)
|
||||
+ {
|
||||
+ g_dbus_method_invocation_return_gerror (invocation, error);
|
||||
+ return G_DBUS_METHOD_INVOCATION_HANDLED;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
- if (instance_path)
|
||||
+ for (i = 0; sandbox_expose != NULL && sandbox_expose[i] != NULL; i++)
|
||||
{
|
||||
- for (i = 0; sandbox_expose != NULL && sandbox_expose[i] != NULL; i++)
|
||||
- g_ptr_array_add (flatpak_argv,
|
||||
- filesystem_sandbox_arg (instance_path, sandbox_expose[i], FALSE));
|
||||
- for (i = 0; sandbox_expose_ro != NULL && sandbox_expose_ro[i] != NULL; i++)
|
||||
- g_ptr_array_add (flatpak_argv,
|
||||
- filesystem_sandbox_arg (instance_path, sandbox_expose_ro[i], TRUE));
|
||||
+ int expose_fd;
|
||||
+
|
||||
+ g_assert (instance_sandbox_fd >= 0);
|
||||
+
|
||||
+ expose_fd = glnx_chaseat (instance_sandbox_fd, sandbox_expose[i],
|
||||
+ GLNX_CHASE_RESOLVE_NO_SYMLINKS |
|
||||
+ GLNX_CHASE_RESOLVE_BENEATH,
|
||||
+ &error);
|
||||
+ if (expose_fd < 0)
|
||||
+ {
|
||||
+ g_dbus_method_invocation_return_gerror (invocation, error);
|
||||
+ return G_DBUS_METHOD_INVOCATION_HANDLED;
|
||||
+ }
|
||||
+
|
||||
+ g_array_append_val (expose_fds, expose_fd);
|
||||
+ /* transfers ownership, can't g_steal_fd with g_array_append_val */
|
||||
+ g_array_append_val (owned_fds, expose_fd);
|
||||
}
|
||||
|
||||
for (i = 0; sandbox_expose_ro != NULL && sandbox_expose_ro[i] != NULL; i++)
|
||||
{
|
||||
- const char *expose = sandbox_expose_ro[i];
|
||||
- g_debug ("exposing %s", expose);
|
||||
+ int expose_fd;
|
||||
+
|
||||
+ g_assert (instance_sandbox_fd >= 0);
|
||||
+
|
||||
+ expose_fd = glnx_chaseat (instance_sandbox_fd, sandbox_expose_ro[i],
|
||||
+ GLNX_CHASE_RESOLVE_NO_SYMLINKS |
|
||||
+ GLNX_CHASE_RESOLVE_BENEATH,
|
||||
+ &error);
|
||||
+ if (expose_fd < 0)
|
||||
+ {
|
||||
+ g_dbus_method_invocation_return_gerror (invocation, error);
|
||||
+ return G_DBUS_METHOD_INVOCATION_HANDLED;
|
||||
+ }
|
||||
+
|
||||
+ g_array_append_val (expose_fds_ro, expose_fd);
|
||||
+ /* transfers ownership, can't g_steal_fd with g_array_append_val */
|
||||
+ g_array_append_val (owned_fds, expose_fd);
|
||||
}
|
||||
|
||||
if (sandbox_expose_fd != NULL)
|
||||
{
|
||||
gsize len = g_variant_n_children (sandbox_expose_fd);
|
||||
+
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
gint32 handle;
|
||||
+
|
||||
g_variant_get_child (sandbox_expose_fd, i, "h", &handle);
|
||||
- if (handle >= 0 && handle < fds_len)
|
||||
+ if (handle >= 0 && handle < fds_len &&
|
||||
+ validate_opath_fd (fds[handle], TRUE, &error))
|
||||
{
|
||||
- int handle_fd = fds[handle];
|
||||
- g_autofree char *path = NULL;
|
||||
- gboolean writable = FALSE;
|
||||
-
|
||||
- path = get_path_for_fd (handle_fd, &writable, &error);
|
||||
-
|
||||
- if (path)
|
||||
- {
|
||||
- g_ptr_array_add (flatpak_argv, filesystem_arg (path, !writable));
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- g_debug ("unable to get path for sandbox-exposed fd %d, ignoring: %s",
|
||||
- handle_fd, error->message);
|
||||
- g_clear_error (&error);
|
||||
- }
|
||||
+ g_array_append_val (expose_fds, fds[handle]);
|
||||
}
|
||||
else
|
||||
{
|
||||
+ g_debug ("Invalid sandbox expose fd: %s", error->message);
|
||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||
G_DBUS_ERROR_INVALID_ARGS,
|
||||
- "No file descriptor for handle %d",
|
||||
+ "No valid file descriptor for handle %d",
|
||||
handle);
|
||||
return G_DBUS_METHOD_INVOCATION_HANDLED;
|
||||
}
|
||||
@@ -1300,31 +1191,20 @@ handle_spawn (PortalFlatpak *object,
|
||||
if (sandbox_expose_fd_ro != NULL)
|
||||
{
|
||||
gsize len = g_variant_n_children (sandbox_expose_fd_ro);
|
||||
+
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
gint32 handle;
|
||||
+
|
||||
g_variant_get_child (sandbox_expose_fd_ro, i, "h", &handle);
|
||||
- if (handle >= 0 && handle < fds_len)
|
||||
+ if (handle >= 0 && handle < fds_len &&
|
||||
+ validate_opath_fd (fds[handle], FALSE, &error))
|
||||
{
|
||||
- int handle_fd = fds[handle];
|
||||
- g_autofree char *path = NULL;
|
||||
- gboolean writable = FALSE;
|
||||
-
|
||||
- path = get_path_for_fd (handle_fd, &writable, &error);
|
||||
-
|
||||
- if (path)
|
||||
- {
|
||||
- g_ptr_array_add (flatpak_argv, filesystem_arg (path, TRUE));
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- g_debug ("unable to get path for sandbox-exposed fd %d, ignoring: %s",
|
||||
- handle_fd, error->message);
|
||||
- g_clear_error (&error);
|
||||
- }
|
||||
+ g_array_append_val (expose_fds_ro, fds[handle]);
|
||||
}
|
||||
else
|
||||
{
|
||||
+ g_debug ("Invalid sandbox expose ro fd: %s", error->message);
|
||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||
G_DBUS_ERROR_INVALID_ARGS,
|
||||
"No file descriptor for handle %d",
|
||||
@@ -1334,20 +1214,40 @@ handle_spawn (PortalFlatpak *object,
|
||||
}
|
||||
}
|
||||
|
||||
+ for (i = 0; i < expose_fds->len; i++)
|
||||
+ {
|
||||
+ int remapped_fd;
|
||||
+
|
||||
+ remapped_fd = fd_map_remap_fd (fd_map, &max_fd, expose_fds->data[i]);
|
||||
+
|
||||
+ g_ptr_array_add (flatpak_argv, g_strdup_printf ("--bind-fd=%d",
|
||||
+ remapped_fd));
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < expose_fds_ro->len; i++)
|
||||
+ {
|
||||
+ int remapped_fd;
|
||||
+
|
||||
+ remapped_fd = fd_map_remap_fd (fd_map, &max_fd, expose_fds_ro->data[i]);
|
||||
+
|
||||
+ g_ptr_array_add (flatpak_argv, g_strdup_printf ("--ro-bind-fd=%d",
|
||||
+ remapped_fd));
|
||||
+ }
|
||||
+
|
||||
empty_app = (arg_flags & FLATPAK_SPAWN_FLAGS_EMPTY_APP) != 0;
|
||||
|
||||
+ if (empty_app && app_fd != NULL)
|
||||
+ {
|
||||
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||
+ G_DBUS_ERROR_INVALID_ARGS,
|
||||
+ "app-fd and EMPTY_APP cannot both be used");
|
||||
+ return G_DBUS_METHOD_INVOCATION_HANDLED;
|
||||
+ }
|
||||
+
|
||||
if (app_fd != NULL)
|
||||
{
|
||||
+ int remapped_fd;
|
||||
gint32 handle = g_variant_get_handle (app_fd);
|
||||
- g_autofree char *path = NULL;
|
||||
-
|
||||
- if (empty_app)
|
||||
- {
|
||||
- g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||
- G_DBUS_ERROR_INVALID_ARGS,
|
||||
- "app-fd and EMPTY_APP cannot both be used");
|
||||
- return G_DBUS_METHOD_INVOCATION_HANDLED;
|
||||
- }
|
||||
|
||||
if (handle >= fds_len || handle < 0)
|
||||
{
|
||||
@@ -1359,18 +1259,11 @@ handle_spawn (PortalFlatpak *object,
|
||||
}
|
||||
|
||||
g_assert (fds != NULL); /* otherwise fds_len would be 0 */
|
||||
- path = get_path_for_fd (fds[handle], NULL, &error);
|
||||
|
||||
- if (path == NULL)
|
||||
- {
|
||||
- g_prefix_error (&error, "Unable to convert /app fd %d into path: ",
|
||||
- fds[handle]);
|
||||
- g_dbus_method_invocation_return_gerror (invocation, error);
|
||||
- return G_DBUS_METHOD_INVOCATION_HANDLED;
|
||||
- }
|
||||
+ remapped_fd = fd_map_remap_fd (fd_map, &max_fd, fds[handle]);
|
||||
|
||||
- g_debug ("Using %s as /app instead of app", path);
|
||||
- g_ptr_array_add (flatpak_argv, g_strdup_printf ("--app-path=%s", path));
|
||||
+ g_ptr_array_add (flatpak_argv, g_strdup_printf ("--app-fd=%d",
|
||||
+ remapped_fd));
|
||||
}
|
||||
else if (empty_app)
|
||||
{
|
||||
@@ -1379,8 +1272,8 @@ handle_spawn (PortalFlatpak *object,
|
||||
|
||||
if (usr_fd != NULL)
|
||||
{
|
||||
+ int remapped_fd;
|
||||
gint32 handle = g_variant_get_handle (usr_fd);
|
||||
- g_autofree char *path = NULL;
|
||||
|
||||
if (handle >= fds_len || handle < 0)
|
||||
{
|
||||
@@ -1392,18 +1285,11 @@ handle_spawn (PortalFlatpak *object,
|
||||
}
|
||||
|
||||
g_assert (fds != NULL); /* otherwise fds_len would be 0 */
|
||||
- path = get_path_for_fd (fds[handle], NULL, &error);
|
||||
|
||||
- if (path == NULL)
|
||||
- {
|
||||
- g_prefix_error (&error, "Unable to convert /usr fd %d into path: ",
|
||||
- fds[handle]);
|
||||
- g_dbus_method_invocation_return_gerror (invocation, error);
|
||||
- return G_DBUS_METHOD_INVOCATION_HANDLED;
|
||||
- }
|
||||
+ remapped_fd = fd_map_remap_fd (fd_map, &max_fd, fds[handle]);
|
||||
|
||||
- g_debug ("Using %s as /usr instead of runtime", path);
|
||||
- g_ptr_array_add (flatpak_argv, g_strdup_printf ("--usr-path=%s", path));
|
||||
+ g_ptr_array_add (flatpak_argv, g_strdup_printf ("--usr-fd=%d",
|
||||
+ remapped_fd));
|
||||
}
|
||||
|
||||
g_ptr_array_add (flatpak_argv, g_strdup_printf ("--runtime=%s", runtime_parts[1]));
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
From 8d1e978c6a582b1603dccb7fe9340e15787f6297 Mon Sep 17 00:00:00 2001
|
||||
From: Xiangzhe <xiangzhedev@gmail.com>
|
||||
Date: Wed, 8 Apr 2026 12:27:28 +0800
|
||||
Subject: [PATCH] run: Fix checking wrong variable in runtime fd selection
|
||||
|
||||
In flatpak_run_app(), the else-if branch that handles
|
||||
FLATPAK_RUN_APP_DEPLOY_USR_ORIGINAL was checking custom_app_fd instead
|
||||
of custom_runtime_fd. When custom_app_fd is APP_EMPTY (-3) and
|
||||
custom_runtime_fd is USR_ORIGINAL (-2), the condition would not match
|
||||
and fall through to g_assert_not_reached(), aborting the process.
|
||||
|
||||
This broke sub-sandbox spawning with --app-path="" (empty app), which
|
||||
is used by steam-runtime-check-requirements to verify that Flatpak's
|
||||
sub-sandbox mechanism works.
|
||||
|
||||
Fixes: ac62ebe3 "run: Use O_PATH fds for the runtime and app deploy directories"
|
||||
Helps: https://github.com/flatpak/flatpak/issues/6568
|
||||
(cherry picked from commit 066babba75d355d077ea11091e5f65d3b0e0d818)
|
||||
---
|
||||
common/flatpak-run.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/common/flatpak-run.c b/common/flatpak-run.c
|
||||
index 9087be23..4ffc5fa3 100644
|
||||
--- a/common/flatpak-run.c
|
||||
+++ b/common/flatpak-run.c
|
||||
@@ -4350,7 +4350,7 @@ flatpak_run_app (FlatpakDecomposed *app_ref,
|
||||
runtime_fd = custom_runtime_fd;
|
||||
runtime_files = custom_runtime_files;
|
||||
}
|
||||
- else if (custom_app_fd == FLATPAK_RUN_APP_DEPLOY_USR_ORIGINAL)
|
||||
+ else if (custom_runtime_fd == FLATPAK_RUN_APP_DEPLOY_USR_ORIGINAL)
|
||||
{
|
||||
original_runtime_target_path = "/usr";
|
||||
runtime_fd = original_runtime_fd;
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,90 @@
|
||||
From a13a7415517cbf1d5073bde05e5b9c3c95de6b16 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Wick <sebastian.wick@redhat.com>
|
||||
Date: Fri, 9 Jan 2026 19:24:44 +0100
|
||||
Subject: [PATCH] utils: Only remove cached files in the cache directory
|
||||
|
||||
The function flatpak_switch_symlink_and_remove is used to implement a
|
||||
cache for ld.so (regenerate_ld_cache). If the active symlink changes to
|
||||
a new cache file, the old cache file is supposed to get removed.
|
||||
|
||||
The symlink still points to the old cache file, so we would remove the
|
||||
file that it points to and then point at the new file.
|
||||
|
||||
Because the symlink is under the app's control, the symlink can point
|
||||
anywhere, and the removal happens in the host context, which allows an
|
||||
app to remove arbitrary files on the host.
|
||||
|
||||
The filename of the cache files are checksums, which means that we can
|
||||
ensure that the link is a file in the same directory of the link by
|
||||
checking that it only contains the chars a-zA-Z0-9.
|
||||
|
||||
(cherry picked from commit c97905c8188ddaad01ee146b57bba6c3fa294113):
|
||||
---
|
||||
common/flatpak-utils.c | 36 +++++++++++++++++++++++++++++++++---
|
||||
1 file changed, 33 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/common/flatpak-utils.c b/common/flatpak-utils.c
|
||||
index 999d88fd..0ab84064 100644
|
||||
--- a/common/flatpak-utils.c
|
||||
+++ b/common/flatpak-utils.c
|
||||
@@ -1344,6 +1344,22 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static gboolean
|
||||
+flatpak_str_is_alphanumeric (const char *arg)
|
||||
+{
|
||||
+ while (*arg != '\0')
|
||||
+ {
|
||||
+ char c = *arg;
|
||||
+
|
||||
+ if (!g_ascii_isalnum (c))
|
||||
+ return FALSE;
|
||||
+
|
||||
+ arg++;
|
||||
+ }
|
||||
+
|
||||
+ return TRUE;
|
||||
+}
|
||||
+
|
||||
/* This atomically replaces a symlink with a new value, removing the
|
||||
* existing symlink target, if it exstis and is different from
|
||||
* @target. This is atomic in the sense that we're guaranteed to
|
||||
@@ -1353,6 +1369,9 @@ out:
|
||||
* symlink for some reason, ending up with neither the old or the new
|
||||
* target. That is fine if the reason for the symlink is keeping a
|
||||
* cache though.
|
||||
+ * The target shall only be a file in the same directory as the symlink, and
|
||||
+ * shall only contain the characters a-zA-Z0-9. This is so that the target of
|
||||
+ * the symlink that gets removed is in the same directory as the link.
|
||||
*/
|
||||
gboolean
|
||||
flatpak_switch_symlink_and_remove (const char *symlink_path,
|
||||
@@ -1396,10 +1415,21 @@ flatpak_switch_symlink_and_remove (const char *symlink_path,
|
||||
g_autofree char *old_target = flatpak_readlink (tmp_path, error);
|
||||
if (old_target == NULL)
|
||||
return FALSE;
|
||||
- if (strcmp (old_target, target) != 0) /* Don't remove old file if its the same as the new one */
|
||||
+
|
||||
+ /* Don't remove old file if its the same as the new one */
|
||||
+ if (strcmp (old_target, target) != 0)
|
||||
{
|
||||
- g_autofree char *old_target_path = g_build_filename (symlink_dir, old_target, NULL);
|
||||
- unlink (old_target_path);
|
||||
+ if (flatpak_str_is_alphanumeric (old_target))
|
||||
+ {
|
||||
+ g_autofree char *old_target_path = NULL;
|
||||
+
|
||||
+ old_target_path = g_build_filename (symlink_dir, old_target, NULL);
|
||||
+ unlink (old_target_path);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ g_warning ("Refusing to delete old link target %s", old_target);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
else if (errno != ENOENT)
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,50 @@
|
||||
From 6a85e0591b6fbc01d9afe6d81bf6748ce2f3e8ac Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Wick <sebastian.wick@redhat.com>
|
||||
Date: Mon, 12 Jan 2026 17:38:02 +0100
|
||||
Subject: [PATCH] utils: Do not follow symlinks in local_open_file
|
||||
|
||||
We use local_open_file in the context of the system helper to open
|
||||
files written by a user. This means that we want to prevent DOS and
|
||||
exposing files which only the system helper has access to.
|
||||
|
||||
To prevent DOS and avoid side-effects, the file is opened with
|
||||
O_NONBLOCK and O_NOCTTY.
|
||||
|
||||
To prevent leaking files, the file is supposed to not open symlinks.
|
||||
This part, we failed at. We check if the opened file is a regular file,
|
||||
but what we actually checked is, if the file a symlink might point at is
|
||||
a regular file.
|
||||
|
||||
Fix this by also specifying O_NOFOLLOW in openat.
|
||||
|
||||
(cherry picked from commit 4a678f463b455c585d38ac4cf4d994e7ce710f8e):
|
||||
---
|
||||
common/flatpak-oci-registry.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/common/flatpak-oci-registry.c b/common/flatpak-oci-registry.c
|
||||
index 2dbd46b5..56853142 100644
|
||||
--- a/common/flatpak-oci-registry.c
|
||||
+++ b/common/flatpak-oci-registry.c
|
||||
@@ -251,6 +251,9 @@ flatpak_oci_registry_new (const char *uri,
|
||||
return oci_registry;
|
||||
}
|
||||
|
||||
+/* Carefully opens a file from a base directory and subpath,
|
||||
+ * making sure that its not a symlink, pipe, etc.
|
||||
+ */
|
||||
static int
|
||||
local_open_file (int dfd,
|
||||
const char *subpath,
|
||||
@@ -262,7 +265,7 @@ local_open_file (int dfd,
|
||||
struct stat tmp_st_buf;
|
||||
|
||||
do
|
||||
- fd = openat (dfd, subpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC | O_NOCTTY);
|
||||
+ fd = openat (dfd, subpath, O_NOFOLLOW | O_RDONLY | O_NONBLOCK | O_CLOEXEC | O_NOCTTY);
|
||||
while (G_UNLIKELY (fd == -1 && errno == EINTR));
|
||||
if (fd == -1)
|
||||
{
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,152 @@
|
||||
From 640c9c2725f67220dd25a5148d6f2bb6fc7ddcf5 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Wick <sebastian.wick@redhat.com>
|
||||
Date: Sat, 7 Feb 2026 21:57:30 +0100
|
||||
Subject: [PATCH] system-helper: Only remove an ongoing pull if users match
|
||||
|
||||
The code would always remove a pull from the hashtable, and then check if the
|
||||
users match and abort if they don't. Either way, the pull gets dropped.
|
||||
|
||||
Fix this by only removing the pull if the dir and the user match.
|
||||
|
||||
(cherry picked from commit a27ec46e8c0ab0ae162f2aa3142dccb6b79d9211):
|
||||
---
|
||||
system-helper/flatpak-system-helper.c | 85 ++++++++++++---------------
|
||||
1 file changed, 36 insertions(+), 49 deletions(-)
|
||||
|
||||
diff --git a/system-helper/flatpak-system-helper.c b/system-helper/flatpak-system-helper.c
|
||||
index 03410e84..5aa3e2ab 100644
|
||||
--- a/system-helper/flatpak-system-helper.c
|
||||
+++ b/system-helper/flatpak-system-helper.c
|
||||
@@ -355,23 +355,31 @@ get_connection_uid (GDBusMethodInvocation *invocation, uid_t *out_uid, GError **
|
||||
}
|
||||
|
||||
static OngoingPull *
|
||||
-take_ongoing_pull_by_dir (const gchar *src_dir)
|
||||
+take_ongoing_pull_by_dir (const char *src_dir,
|
||||
+ uid_t uid)
|
||||
{
|
||||
OngoingPull *pull = NULL;
|
||||
- gpointer key, value;
|
||||
+ char *cache_dir_name = NULL;
|
||||
|
||||
G_LOCK (cache_dirs_in_use);
|
||||
- /* Keep src_dir key inside hashtable but remove its OngoingPull
|
||||
- * value and set it to NULL. This way src_dir is still marked
|
||||
- * as in-use (as Deploy or CancelPull might be executing on it,
|
||||
- * whereas OngoingPull ownership is transferred to respective
|
||||
- * callers. */
|
||||
- if (g_hash_table_steal_extended (cache_dirs_in_use, src_dir, &key, &value))
|
||||
- {
|
||||
- if (value)
|
||||
+ if (g_hash_table_steal_extended (cache_dirs_in_use, src_dir,
|
||||
+ (gpointer) &cache_dir_name,
|
||||
+ (gpointer) &pull))
|
||||
+ {
|
||||
+ if (pull && pull->uid == uid)
|
||||
{
|
||||
- g_hash_table_insert (cache_dirs_in_use, key, NULL);
|
||||
- pull = value;
|
||||
+ /* Keep src_dir key inside hashtable but remove its OngoingPull
|
||||
+ * value and set it to NULL. This way src_dir is still marked
|
||||
+ * as in-use (as Deploy or CancelPull might be executing on it,
|
||||
+ * whereas OngoingPull ownership is transferred to respective
|
||||
+ * callers. */
|
||||
+ g_hash_table_insert (cache_dirs_in_use, cache_dir_name, NULL);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* Otherwise, re-insert what is currently there and return NULL */
|
||||
+ g_hash_table_insert (cache_dirs_in_use, cache_dir_name, pull);
|
||||
+ pull = NULL;
|
||||
}
|
||||
}
|
||||
G_UNLOCK (cache_dirs_in_use);
|
||||
@@ -423,6 +431,9 @@ handle_deploy (FlatpakSystemHelper *object,
|
||||
|
||||
if (strlen (arg_repo_path) > 0)
|
||||
{
|
||||
+ g_autoptr(GError) local_error = NULL;
|
||||
+ uid_t uid;
|
||||
+
|
||||
if (!g_file_query_exists (repo_file, NULL))
|
||||
{
|
||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
|
||||
@@ -430,30 +441,17 @@ handle_deploy (FlatpakSystemHelper *object,
|
||||
return G_DBUS_METHOD_INVOCATION_HANDLED;
|
||||
}
|
||||
|
||||
+ /* Ensure that pull's uid is same as the caller's uid */
|
||||
+ if (!get_connection_uid (invocation, &uid, &local_error))
|
||||
+ {
|
||||
+ g_dbus_method_invocation_return_gerror (invocation, local_error);
|
||||
+ return G_DBUS_METHOD_INVOCATION_HANDLED;
|
||||
+ }
|
||||
+
|
||||
src_dir = g_path_get_dirname (arg_repo_path);
|
||||
- ongoing_pull = take_ongoing_pull_by_dir (src_dir);
|
||||
+ ongoing_pull = take_ongoing_pull_by_dir (src_dir, uid);
|
||||
if (ongoing_pull != NULL)
|
||||
{
|
||||
- g_autoptr(GError) local_error = NULL;
|
||||
- uid_t uid;
|
||||
-
|
||||
- /* Ensure that pull's uid is same as the caller's uid */
|
||||
- if (!get_connection_uid (invocation, &uid, &local_error))
|
||||
- {
|
||||
- g_dbus_method_invocation_return_gerror (invocation, local_error);
|
||||
- return G_DBUS_METHOD_INVOCATION_HANDLED;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- if (ongoing_pull->uid != uid)
|
||||
- {
|
||||
- g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
|
||||
- "Ongoing pull's uid(%d) does not match with peer uid(%d)",
|
||||
- ongoing_pull->uid, uid);
|
||||
- return G_DBUS_METHOD_INVOCATION_HANDLED;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
terminate_revokefs_backend (ongoing_pull);
|
||||
|
||||
if (!flatpak_canonicalize_permissions (AT_FDCWD,
|
||||
@@ -735,31 +733,20 @@ handle_cancel_pull (FlatpakSystemHelper *object,
|
||||
return G_DBUS_METHOD_INVOCATION_HANDLED;
|
||||
}
|
||||
|
||||
- ongoing_pull = take_ongoing_pull_by_dir (arg_src_dir);
|
||||
- if (ongoing_pull == NULL)
|
||||
+ if (!get_connection_uid (invocation, &uid, &error))
|
||||
{
|
||||
- g_set_error (&error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
|
||||
- "Cannot find ongoing pull to cancel at %s", arg_src_dir);
|
||||
g_dbus_method_invocation_return_gerror (invocation, error);
|
||||
return G_DBUS_METHOD_INVOCATION_HANDLED;
|
||||
}
|
||||
|
||||
- /* Ensure that pull's uid is same as the caller's uid */
|
||||
- if (!get_connection_uid (invocation, &uid, &error))
|
||||
+ ongoing_pull = take_ongoing_pull_by_dir (arg_src_dir, uid);
|
||||
+ if (ongoing_pull == NULL)
|
||||
{
|
||||
+ g_set_error (&error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
|
||||
+ "Cannot find ongoing pull to cancel at %s", arg_src_dir);
|
||||
g_dbus_method_invocation_return_gerror (invocation, error);
|
||||
return G_DBUS_METHOD_INVOCATION_HANDLED;
|
||||
}
|
||||
- else
|
||||
- {
|
||||
- if (ongoing_pull->uid != uid)
|
||||
- {
|
||||
- g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
|
||||
- "Ongoing pull's uid(%d) does not match with peer uid(%d)",
|
||||
- ongoing_pull->uid, uid);
|
||||
- return G_DBUS_METHOD_INVOCATION_HANDLED;
|
||||
- }
|
||||
- }
|
||||
|
||||
ongoing_pull->preserve_pull = (arg_flags & FLATPAK_HELPER_CANCEL_PULL_FLAGS_PRESERVE_PULL) != 0;
|
||||
ongoing_pull_free (ongoing_pull);
|
||||
--
|
||||
2.54.0
|
||||
|
||||
6134
SOURCES/flatpak-1.12.x-update-libglnx-for-glnx-chaseseat.patch
Normal file
6134
SOURCES/flatpak-1.12.x-update-libglnx-for-glnx-chaseseat.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -3,7 +3,7 @@
|
||||
|
||||
Name: flatpak
|
||||
Version: 1.12.9
|
||||
Release: 3%{?dist}
|
||||
Release: 4%{?dist}
|
||||
Summary: Application deployment framework for desktop apps
|
||||
|
||||
License: LGPLv2+
|
||||
@ -21,6 +21,44 @@ Patch0: flatpak-Revert-selinux-Permit-using-systemd-userdbd.patch
|
||||
# Backported upstream patch for CVE-2024-42472
|
||||
Patch1: flatpak-1.12.x-CVE-2024-42472.patch
|
||||
|
||||
# CVE-2026-34078
|
||||
Patch100: flatpak-1.12.x-update-libglnx-for-glnx-chaseseat.patch
|
||||
Patch101: CVE-2026-34078-1-flatpak-bwrap-add-dup-ing-variant-flatpak-bwrap-add-args-data-fd-dup.patch
|
||||
Patch102: CVE-2026-34078-2-utils-add-flatpak-parse-fd.patch
|
||||
Patch103: CVE-2026-34078-3-flatpak-bwrap-use-glnx-close-fd-as-clear-func.patch
|
||||
Patch104: CVE-2026-34078-4-run-use-o-path-fds-for-the-runtime-and-app-deploy-directories.patch
|
||||
Patch105: CVE-2026-34078-5-run-add-usr-fd-and-app-fd-options.patch
|
||||
Patch106: CVE-2026-34078-6-run-add-ro-bind-fds-to-flatpak-run-app.patch
|
||||
Patch107: CVE-2026-34078-7-run-add-ro-bind-fd-options.patch
|
||||
Patch108: CVE-2026-34078-8-portal-use-bind-fd-app-fd-and-usr-fd-options-to-avoid-races.patch
|
||||
Patch109: CVE-2026-34078-9-run-fix-checking-wrong-variable-in-runtime-fd-selection.patch
|
||||
Patch110: CVE-2026-34078-10-run-mount-original-app-on-run-parent-app-when-using-app-path.patch
|
||||
Patch111: CVE-2026-34078-11-portal-update-max-fd-after-creating-the-instance-id-pipe.patch
|
||||
Patch112: CVE-2026-34078-12-run-fix-fd-tracking-in-flatpak-run-add-app-info-args.patch
|
||||
Patch113: CVE-2026-34078-13-utils-improve-error-message-when-passing-an-fd-numer-which-is-not-a-fd.patch
|
||||
Patch114: CVE-2026-34078-14-run-do-not-close-bind-ro-bind.patch
|
||||
Patch115: CVE-2026-34078-15-run-use-the-same-fd-validation-for-all-fd-options.patch
|
||||
Patch116: CVE-2026-34078-16-run-add-bind-fd-and-ro-bind-fd-binds-after-all-other-binds.patch
|
||||
Patch117: CVE-2026-34078-17-portal-use-g-array-index-to-read-from-expose-fds-expose-fds-ro.patch
|
||||
Patch118: CVE-2026-34078-18-run-fix-backport-mistake.patch
|
||||
Patch119: CVE-2026-34078-19-run-cope-with-an-empty-runtime.patch
|
||||
Patch120: CVE-2026-34078-20-dir-in-apply-extra-data-don-t-assume-there-is-always-a-runtime.patch
|
||||
Patch121: CVE-2026-34078-21-utils-add-flatpak-set-cloexec.patch
|
||||
Patch122: CVE-2026-34078-22-run-context-mark-fd-arguments-as-close-on-exec.patch
|
||||
Patch123: CVE-2026-34078-23-utils-move-flatpak-get-path-for-fd-to-here.patch
|
||||
Patch124: CVE-2026-34078-24-portal-avoid-crash-if-sandbox-expose-ro-fd-is-out-of-range.patch
|
||||
Patch125: CVE-2026-34078-25-portal-log-and-ignore-unusable-sandbox-expose-fds-instead-of-erroring.patch
|
||||
Patch126: CVE-2026-34078-26-portal-reinstate-flatpak-get-path-for-fd-checks.patch
|
||||
Patch127: CVE-2026-34078-27-libtest-allow-adding-a-new-ref-to-an-existing-temporary-ostree-repo.patch
|
||||
Patch128: CVE-2026-34078-28-app-context-never-close-fds-0-1-or-2.patch
|
||||
Patch129: CVE-2026-34078-29-app-context-factor-out-flatpak-accept-fd-argument.patch
|
||||
|
||||
# CVE-2026-34079
|
||||
Patch130: CVE-2026-34079-1-utils-only-remove-cached-files-in-the-cache-directory.patch
|
||||
Patch131: CVE-2026-34079-2-utils-do-not-follow-symlinks-in-local-open-file.patch
|
||||
Patch132: CVE-2026-34079-3-system-helper-only-remove-an-ongoing-pull-if-users-match.patch
|
||||
|
||||
|
||||
BuildRequires: pkgconfig(appstream-glib)
|
||||
BuildRequires: pkgconfig(dconf)
|
||||
BuildRequires: pkgconfig(fuse)
|
||||
@ -280,6 +318,12 @@ fi
|
||||
|
||||
|
||||
%changelog
|
||||
* Wed May 20 2026 Jan Grulich <jgrulich@redhat.com> - 1.12.9-4
|
||||
- Fix arbitrary code execution via crafted symlinks in sandbox-expose options
|
||||
Resolves: RHEL-165633
|
||||
- Fix arbitrary file deletion on host via improper cache file path validation
|
||||
Resolves: RHEL-170160
|
||||
|
||||
* Wed Sep 04 2024 Kalev Lember <klember@redhat.com> - 1.12.9-3
|
||||
- Fix previous changelog entry
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user