import UBI flatpak-1.16.0-9.el10_2.1
This commit is contained in:
parent
e37ada1959
commit
6dde1ae8d0
2470
CVE-2026-34078-1-update-subtree-libglnx-2026-04-07.patch
Normal file
2470
CVE-2026-34078-1-update-subtree-libglnx-2026-04-07.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,38 @@
|
||||
From d19f44408000b53b6d61d3e60a3c65104dc5a8c6 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 055c721d..f44c66ff 100644
|
||||
--- a/common/flatpak-run.c
|
||||
+++ b/common/flatpak-run.c
|
||||
@@ -3203,7 +3203,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,34 @@
|
||||
From ccd9c8a7fa8bee1b728e683c2d478f4408cd651c 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 f44c66ff..b90af672 100644
|
||||
--- a/common/flatpak-run.c
|
||||
+++ b/common/flatpak-run.c
|
||||
@@ -3335,6 +3335,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 2e2f4a430b784163614403b333ab3990c9354db3 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 5c0935a1..a67ee330 100644
|
||||
--- a/portal/flatpak-portal.c
|
||||
+++ b/portal/flatpak-portal.c
|
||||
@@ -1150,6 +1150,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,123 @@
|
||||
From bd41305b98373d762cc02395d9fe7b9486da20d4 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 | 33 ++++++++++++++++-----------------
|
||||
1 file changed, 16 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/common/flatpak-run.c b/common/flatpak-run.c
|
||||
index b90af672..5882b2a9 100644
|
||||
--- a/common/flatpak-run.c
|
||||
+++ b/common/flatpak-run.c
|
||||
@@ -1366,7 +1366,7 @@ 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,
|
||||
char **instance_id_host_private_dir_out,
|
||||
char **instance_id_out,
|
||||
@@ -1374,7 +1374,11 @@ flatpak_run_add_app_info_args (FlatpakBwrap *bwrap,
|
||||
{
|
||||
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;
|
||||
@@ -1523,8 +1527,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),
|
||||
@@ -1535,7 +1539,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));
|
||||
@@ -1544,9 +1547,9 @@ flatpak_run_add_app_info_args (FlatpakBwrap *bwrap,
|
||||
|
||||
flatpak_bwrap_add_args (bwrap, "--perms", "0600", NULL);
|
||||
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,
|
||||
@@ -1563,8 +1566,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));
|
||||
@@ -1587,10 +1588,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;
|
||||
@@ -1600,13 +1597,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);
|
||||
@@ -3556,7 +3554,8 @@ 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,
|
||||
+ &app_info_path,
|
||||
+ g_steal_fd (&instance_id_fd),
|
||||
&instance_id_host_dir, &instance_id_host_private_dir,
|
||||
&instance_id, error))
|
||||
return FALSE;
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,28 @@
|
||||
From e2ef538e8d70f8ddaf1adf201c3bb1578d0444f1 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 dbc46951..7e69e8be 100644
|
||||
--- a/common/flatpak-utils.c
|
||||
+++ b/common/flatpak-utils.c
|
||||
@@ -2520,8 +2520,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
|
||||
|
||||
32
CVE-2026-34078-15-run-do-not-close-bind-ro-bind.patch
Normal file
32
CVE-2026-34078-15-run-do-not-close-bind-ro-bind.patch
Normal file
@ -0,0 +1,32 @@
|
||||
From e654ebade0b9154830563c55c0a5f426b41fd46d 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 0bfc311d..256f7828 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 c89a0c509ad315ccf5157e9faebb4e243bed165c 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 256f7828..bca4d865 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,97 @@
|
||||
From 6118b415e4ed1e35852736c9a28585f4093bf246 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 | 64 ++++++++++++++++++++++----------------------
|
||||
1 file changed, 32 insertions(+), 32 deletions(-)
|
||||
|
||||
diff --git a/common/flatpak-run.c b/common/flatpak-run.c
|
||||
index 5882b2a9..a8088a92 100644
|
||||
--- a/common/flatpak-run.c
|
||||
+++ b/common/flatpak-run.c
|
||||
@@ -3585,6 +3585,38 @@ flatpak_run_app (FlatpakDecomposed *app_ref,
|
||||
flatpak_bwrap_add_arg_printf (bwrap, "/run/user/%d", getuid ());
|
||||
}
|
||||
|
||||
+ if (!flatpak_run_add_dconf_args (bwrap, app_id, metakey, error))
|
||||
+ return FALSE;
|
||||
+
|
||||
+ if (!sandboxed && !(flags & FLATPAK_RUN_FLAG_NO_DOCUMENTS_PORTAL))
|
||||
+ add_document_portal_args (bwrap, app_id, &doc_mount_path);
|
||||
+
|
||||
+ if (!flatpak_run_add_environment_args (bwrap, app_info_path, flags,
|
||||
+ app_id, app_context, app_id_dir, previous_app_id_dirs,
|
||||
+ per_app_dir_lock_fd, instance_id,
|
||||
+ &exports, cancellable, error))
|
||||
+ return FALSE;
|
||||
+
|
||||
+ if (per_app_dir_lock_path != NULL)
|
||||
+ {
|
||||
+ static const char lock[] = "/run/flatpak/per-app-dirs-ref";
|
||||
+
|
||||
+ flatpak_bwrap_add_args (bwrap,
|
||||
+ "--ro-bind", per_app_dir_lock_path, lock,
|
||||
+ "--lock-file", lock,
|
||||
+ NULL);
|
||||
+ }
|
||||
+
|
||||
+ flatpak_run_add_socket_args_late (bwrap, app_context->shares);
|
||||
+ add_font_path_args (bwrap);
|
||||
+ add_icon_path_args (bwrap);
|
||||
+
|
||||
+ flatpak_bwrap_add_args (bwrap,
|
||||
+ /* Not in base, because we don't want this for flatpak build */
|
||||
+ "--symlink", "/app/lib/debug/source", "/run/build",
|
||||
+ "--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);
|
||||
@@ -3619,38 +3651,6 @@ flatpak_run_app (FlatpakDecomposed *app_ref,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
- if (!flatpak_run_add_dconf_args (bwrap, app_id, metakey, error))
|
||||
- return FALSE;
|
||||
-
|
||||
- if (!sandboxed && !(flags & FLATPAK_RUN_FLAG_NO_DOCUMENTS_PORTAL))
|
||||
- add_document_portal_args (bwrap, app_id, &doc_mount_path);
|
||||
-
|
||||
- if (!flatpak_run_add_environment_args (bwrap, app_info_path, flags,
|
||||
- app_id, app_context, app_id_dir, previous_app_id_dirs,
|
||||
- per_app_dir_lock_fd, instance_id,
|
||||
- &exports, cancellable, error))
|
||||
- return FALSE;
|
||||
-
|
||||
- if (per_app_dir_lock_path != NULL)
|
||||
- {
|
||||
- static const char lock[] = "/run/flatpak/per-app-dirs-ref";
|
||||
-
|
||||
- flatpak_bwrap_add_args (bwrap,
|
||||
- "--ro-bind", per_app_dir_lock_path, lock,
|
||||
- "--lock-file", lock,
|
||||
- NULL);
|
||||
- }
|
||||
-
|
||||
- flatpak_run_add_socket_args_late (bwrap, app_context->shares);
|
||||
- add_font_path_args (bwrap);
|
||||
- add_icon_path_args (bwrap);
|
||||
-
|
||||
- flatpak_bwrap_add_args (bwrap,
|
||||
- /* Not in base, because we don't want this for flatpak build */
|
||||
- "--symlink", "/app/lib/debug/source", "/run/build",
|
||||
- "--symlink", "/usr/lib/debug/source", "/run/build-runtime",
|
||||
- NULL);
|
||||
-
|
||||
if (cwd)
|
||||
flatpak_bwrap_add_args (bwrap, "--chdir", cwd, NULL);
|
||||
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
From 8e71548ab56a97b88c7d34d68a6b04f6d430b2aa 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 a67ee330..0550a379 100644
|
||||
--- a/portal/flatpak-portal.c
|
||||
+++ b/portal/flatpak-portal.c
|
||||
@@ -1294,7 +1294,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));
|
||||
@@ -1304,7 +1304,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
CVE-2026-34078-19-run-fix-backport-mistake.patch
Normal file
28
CVE-2026-34078-19-run-fix-backport-mistake.patch
Normal file
@ -0,0 +1,28 @@
|
||||
From ac540672bb6598285fd333e3863335d27236762b 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 bca4d865..23b9f368 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
|
||||
|
||||
@ -0,0 +1,61 @@
|
||||
From 36bd977772ea0df7159ff207f89564bfccd3b0ca 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 9effed8a..d7a73304 100644
|
||||
--- a/common/flatpak-bwrap-private.h
|
||||
+++ b/common/flatpak-bwrap-private.h
|
||||
@@ -63,6 +63,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 f7e8b10e..a3d29782 100644
|
||||
--- a/common/flatpak-bwrap.c
|
||||
+++ b/common/flatpak-bwrap.c
|
||||
@@ -146,6 +146,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,190 @@
|
||||
From ab8ca4d6a02900974c08694f54903b2616875bf0 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Wick <sebastian.wick@redhat.com>
|
||||
Date: Wed, 8 Apr 2026 14:20:53 +0200
|
||||
Subject: [PATCH] tests/test-run-custom: Test --usr-path, --usr-fd, --app-path,
|
||||
--app-fd
|
||||
|
||||
---
|
||||
tests/test-matrix/meson.build | 2 +
|
||||
tests/test-run-custom.sh | 156 ++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 158 insertions(+)
|
||||
create mode 100755 tests/test-run-custom.sh
|
||||
|
||||
diff --git a/tests/test-matrix/meson.build b/tests/test-matrix/meson.build
|
||||
index fd0b5034..ef85b7ec 100644
|
||||
--- a/tests/test-matrix/meson.build
|
||||
+++ b/tests/test-matrix/meson.build
|
||||
@@ -45,4 +45,6 @@ wrapped_tests += {'name' : 'test-unused.sh', 'script' : 'test-unused.sh'}
|
||||
wrapped_tests += {'name' : 'test-prune.sh', 'script' : 'test-prune.sh'}
|
||||
wrapped_tests += {'name' : 'test-seccomp.sh', 'script' : 'test-seccomp.sh'}
|
||||
wrapped_tests += {'name' : 'test-repair.sh', 'script' : 'test-repair.sh'}
|
||||
wrapped_tests += {'name' : 'test-preinstall.sh', 'script' : 'test-preinstall.sh'}
|
||||
+wrapped_tests += {'name' : 'test-run-custom@user.wrap', 'script' : 'test-run-custom.sh'}
|
||||
+wrapped_tests += {'name' : 'test-run-custom@system.wrap', 'script' : 'test-run-custom.sh'}
|
||||
\ No newline at end of file
|
||||
diff --git a/tests/test-run-custom.sh b/tests/test-run-custom.sh
|
||||
new file mode 100755
|
||||
index 00000000..f8a11f03
|
||||
--- /dev/null
|
||||
+++ b/tests/test-run-custom.sh
|
||||
@@ -0,0 +1,156 @@
|
||||
+#!/bin/bash
|
||||
+#
|
||||
+# Copyright (C) 2026 Red Hat, Inc.
|
||||
+#
|
||||
+# This library is free software; you can redistribute it and/or
|
||||
+# modify it under the terms of the GNU Lesser General Public
|
||||
+# License as published by the Free Software Foundation; either
|
||||
+# version 2 of the License, or (at your option) any later version.
|
||||
+#
|
||||
+# This library is distributed in the hope that it will be useful,
|
||||
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+# Lesser General Public License for more details.
|
||||
+#
|
||||
+# You should have received a copy of the GNU Lesser General Public
|
||||
+# License along with this library; if not, write to the
|
||||
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
+# Boston, MA 02111-1307, USA.
|
||||
+
|
||||
+set -euo pipefail
|
||||
+
|
||||
+. "$(dirname "$0")/libtest.sh"
|
||||
+
|
||||
+skip_without_bwrap
|
||||
+skip_revokefs_without_fuse
|
||||
+
|
||||
+echo "1..10"
|
||||
+
|
||||
+# Use stable rather than master as the branch so we can test that the run
|
||||
+# command automatically finds the branch correctly
|
||||
+setup_repo "" "" stable
|
||||
+install_repo "" stable
|
||||
+
|
||||
+setup_repo_no_add custom org.test.Collection.Custom master
|
||||
+make_updated_runtime custom org.test.Collection.Custom master CUSTOM
|
||||
+make_updated_app custom org.test.Collection.Custom master CUSTOM
|
||||
+
|
||||
+ostree checkout -U --repo=repos/custom runtime/org.test.Platform/${ARCH}/master custom-runtime >&2
|
||||
+ostree checkout -U --repo=repos/custom app/org.test.Hello/$ARCH/master custom-app >&2
|
||||
+
|
||||
+cat custom-runtime/files/bin/runtime_hello.sh > runtime_hello
|
||||
+assert_file_has_content runtime_hello "runtimeCUSTOM"
|
||||
+cat custom-app/files/bin/hello.sh > app_hello
|
||||
+assert_file_has_content app_hello "sandboxCUSTOM"
|
||||
+
|
||||
+run org.test.Hello > hello_out
|
||||
+assert_file_has_content hello_out '^Hello world, from a sandbox$'
|
||||
+
|
||||
+run --command=/usr/bin/runtime_hello.sh org.test.Hello > hello_out
|
||||
+assert_file_has_content hello_out '^Hello world, from a runtime$'
|
||||
+
|
||||
+ok "setup"
|
||||
+
|
||||
+! run --app-path="" --command=/app/bin/hello.sh org.test.Hello > /dev/null
|
||||
+
|
||||
+run --app-path="" --command=/usr/bin/runtime_hello.sh org.test.Hello > hello_out
|
||||
+assert_file_has_content hello_out '^Hello world, from a runtime$'
|
||||
+
|
||||
+run --app-path="" --command=/run/parent/app/bin/hello.sh org.test.Hello > hello_out
|
||||
+assert_file_has_content hello_out '^Hello world, from a sandbox$'
|
||||
+
|
||||
+! run --app-path="" --command=/run/parent/usr/bin/runtime_hello.sh org.test.Hello > /dev/null
|
||||
+
|
||||
+ok "empty app path"
|
||||
+
|
||||
+run --app-path=custom-app/files --command=/app/bin/hello.sh org.test.Hello > hello_out
|
||||
+assert_file_has_content hello_out '^Hello world, from a sandboxCUSTOM$'
|
||||
+
|
||||
+run --app-path=custom-app/files --command=/usr/bin/runtime_hello.sh org.test.Hello > hello_out
|
||||
+assert_file_has_content hello_out '^Hello world, from a runtime$'
|
||||
+
|
||||
+run --app-path=custom-app/files --command=/run/parent/app/bin/hello.sh org.test.Hello > hello_out
|
||||
+assert_file_has_content hello_out '^Hello world, from a sandbox$'
|
||||
+
|
||||
+! run --app-path=custom-app/files --command=/run/parent/usr/bin/runtime_hello.sh org.test.Hello > /dev/null
|
||||
+
|
||||
+ok "custom app path"
|
||||
+
|
||||
+! run --app-path=path-which-does-not-exist org.test.Hello > /dev/null
|
||||
+
|
||||
+ok "bad custom app path"
|
||||
+
|
||||
+exec 3< custom-app/files
|
||||
+run --app-fd=3 --command=/app/bin/hello.sh org.test.Hello > hello_out
|
||||
+assert_file_has_content hello_out '^Hello world, from a sandboxCUSTOM$'
|
||||
+exec 3>&-
|
||||
+
|
||||
+! run --app-fd=3 --command=/app/bin/hello.sh org.test.Hello > /dev/null
|
||||
+
|
||||
+ok "custom app fd"
|
||||
+
|
||||
+run --usr-path=custom-runtime/files --command=/app/bin/hello.sh org.test.Hello > hello_out
|
||||
+assert_file_has_content hello_out '^Hello world, from a sandbox$'
|
||||
+
|
||||
+run --usr-path=custom-runtime/files --command=/usr/bin/runtime_hello.sh org.test.Hello > hello_out
|
||||
+assert_file_has_content hello_out '^Hello world, from a runtimeCUSTOM$'
|
||||
+
|
||||
+! run --usr-path=custom-runtime/files --command=/run/parent/app/bin/hello.sh org.test.Hello > /dev/null
|
||||
+
|
||||
+run --usr-path=custom-runtime/files --command=/run/parent/usr/bin/runtime_hello.sh org.test.Hello > hello_out
|
||||
+assert_file_has_content hello_out '^Hello world, from a runtime$'
|
||||
+
|
||||
+ok "custom usr path"
|
||||
+
|
||||
+! run --usr-path=path-which-does-not-exist org.test.Hello > /dev/null
|
||||
+
|
||||
+ok "bad custom usr path"
|
||||
+
|
||||
+exec 3< custom-runtime/files
|
||||
+run --usr-fd=3 --command=/app/bin/hello.sh org.test.Hello > hello_out
|
||||
+assert_file_has_content hello_out '^Hello world, from a sandbox$'
|
||||
+exec 3>&-
|
||||
+
|
||||
+exec 3< custom-runtime/files
|
||||
+run --usr-fd=3 --command=/usr/bin/runtime_hello.sh org.test.Hello > hello_out
|
||||
+assert_file_has_content hello_out '^Hello world, from a runtimeCUSTOM$'
|
||||
+exec 3>&-
|
||||
+
|
||||
+! run --usr-fd=3 --command=/app/bin/hello.sh org.test.Hello > /dev/null
|
||||
+
|
||||
+ok "custom usr fd"
|
||||
+
|
||||
+run --usr-path=custom-runtime/files --app-path=custom-app/files \
|
||||
+ --command=/app/bin/hello.sh org.test.Hello > hello_out
|
||||
+assert_file_has_content hello_out '^Hello world, from a sandboxCUSTOM$'
|
||||
+
|
||||
+run --usr-path=custom-runtime/files --app-path=custom-app/files \
|
||||
+ --command=/usr/bin/runtime_hello.sh org.test.Hello > hello_out
|
||||
+assert_file_has_content hello_out '^Hello world, from a runtimeCUSTOM$'
|
||||
+
|
||||
+run --usr-path=custom-runtime/files --app-path=custom-app/files \
|
||||
+ --command=/run/parent/app/bin/hello.sh org.test.Hello > hello_out
|
||||
+assert_file_has_content hello_out '^Hello world, from a sandbox$'
|
||||
+
|
||||
+run --usr-path=custom-runtime/files --app-path=custom-app/files \
|
||||
+ --command=/run/parent/usr/bin/runtime_hello.sh org.test.Hello > hello_out
|
||||
+assert_file_has_content hello_out '^Hello world, from a runtime$'
|
||||
+
|
||||
+ok "custom usr and app path"
|
||||
+
|
||||
+! run --usr-path=custom-runtime/files --app-path="" \
|
||||
+ --command=/app/bin/hello.sh org.test.Hello > /dev/null
|
||||
+
|
||||
+run --usr-path=custom-runtime/files --app-path="" \
|
||||
+ --command=/usr/bin/runtime_hello.sh org.test.Hello > hello_out
|
||||
+assert_file_has_content hello_out '^Hello world, from a runtimeCUSTOM$'
|
||||
+
|
||||
+run --usr-path=custom-runtime/files --app-path="" \
|
||||
+ --command=/run/parent/app/bin/hello.sh org.test.Hello > hello_out
|
||||
+assert_file_has_content hello_out '^Hello world, from a sandbox$'
|
||||
+
|
||||
+run --usr-path=custom-runtime/files --app-path="" \
|
||||
+ --command=/run/parent/usr/bin/runtime_hello.sh org.test.Hello > hello_out
|
||||
+assert_file_has_content hello_out '^Hello world, from a runtime$'
|
||||
+
|
||||
+ok "custom usr and empty app path"
|
||||
\ No newline at end of file
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,56 @@
|
||||
From 8ebffc2ad37fb5f2c03641506e8091aee53defd8 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Wick <sebastian.wick@redhat.com>
|
||||
Date: Wed, 8 Apr 2026 21:55:22 +0200
|
||||
Subject: [PATCH] tests/test-run-custom: Test --bind-fd and --ro-bind-fd
|
||||
|
||||
---
|
||||
tests/test-run-custom.sh | 27 +++++++++++++++++++++++++--
|
||||
1 file changed, 25 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/tests/test-run-custom.sh b/tests/test-run-custom.sh
|
||||
index f8a11f03..94c32416 100755
|
||||
--- a/tests/test-run-custom.sh
|
||||
+++ b/tests/test-run-custom.sh
|
||||
@@ -24,7 +24,7 @@ set -euo pipefail
|
||||
skip_without_bwrap
|
||||
skip_revokefs_without_fuse
|
||||
|
||||
-echo "1..10"
|
||||
+echo "1..11"
|
||||
|
||||
# Use stable rather than master as the branch so we can test that the run
|
||||
# command automatically finds the branch correctly
|
||||
@@ -153,4 +153,27 @@ run --usr-path=custom-runtime/files --app-path="" \
|
||||
--command=/run/parent/usr/bin/runtime_hello.sh org.test.Hello > hello_out
|
||||
assert_file_has_content hello_out '^Hello world, from a runtime$'
|
||||
|
||||
-ok "custom usr and empty app path"
|
||||
\ No newline at end of file
|
||||
+ok "custom usr and empty app path"
|
||||
+
|
||||
+path="$(readlink -f .)/foo"
|
||||
+echo "bar" > "${path}"
|
||||
+
|
||||
+exec 3< "${path}"
|
||||
+run --bind-fd=3 --command=cat org.test.Hello "${path}" > hello_out
|
||||
+assert_file_has_content hello_out '^bar$'
|
||||
+
|
||||
+exec 3< "${path}"
|
||||
+run --bind-fd=3 --command=bash org.test.Hello -c "echo baz > ${path}" > /dev/null
|
||||
+assert_file_has_content "${path}" '^baz$'
|
||||
+exec 3>&-
|
||||
+
|
||||
+exec 3< "${path}"
|
||||
+run --ro-bind-fd=3 --command=cat org.test.Hello "${path}" > hello_out
|
||||
+assert_file_has_content hello_out '^baz$'
|
||||
+exec 3>&-
|
||||
+
|
||||
+exec 3< "${path}"
|
||||
+! run --ro-bind-fd=3 --command=bash org.test.Hello -c "echo baz > ${path}" > /dev/null
|
||||
+exec 3>&-
|
||||
+
|
||||
+ok "bind-fd and ro-bind-fd"
|
||||
\ No newline at end of file
|
||||
--
|
||||
2.54.0
|
||||
|
||||
110
CVE-2026-34078-22-run-cope-with-an-empty-runtime.patch
Normal file
110
CVE-2026-34078-22-run-cope-with-an-empty-runtime.patch
Normal file
@ -0,0 +1,110 @@
|
||||
From b942152bde980cde51e933359e4ba3be527ae3ed 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, 23 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/common/flatpak-run.c b/common/flatpak-run.c
|
||||
index a8088a92..f176e884 100644
|
||||
--- a/common/flatpak-run.c
|
||||
+++ b/common/flatpak-run.c
|
||||
@@ -1618,6 +1618,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)
|
||||
@@ -1630,6 +1634,8 @@ add_tzdata_args (FlatpakBwrap *bwrap,
|
||||
glnx_autofd int zoneinfo_fd = -1;
|
||||
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);
|
||||
@@ -1638,10 +1644,11 @@ add_tzdata_args (FlatpakBwrap *bwrap,
|
||||
|
||||
tzdir_fd = glnx_chaseat (AT_FDCWD, tzdir, GLNX_CHASE_MUST_BE_DIRECTORY, 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);
|
||||
|
||||
/* Check for host /usr/share/zoneinfo */
|
||||
if (tzdir_fd >= 0 && zoneinfo_fd >= 0)
|
||||
@@ -1652,7 +1659,7 @@ add_tzdata_args (FlatpakBwrap *bwrap,
|
||||
"--symlink", localtime_content, "/etc/localtime",
|
||||
NULL);
|
||||
}
|
||||
- else
|
||||
+ else if (runtime_fd >= 0)
|
||||
{
|
||||
g_autofree char *runtime_zoneinfo = NULL;
|
||||
glnx_autofd int runtime_zoneinfo_fd = -1;
|
||||
@@ -2163,6 +2170,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,
|
||||
@@ -2226,6 +2237,10 @@ static const char *const sysfs_dirs[] =
|
||||
"/sys/devices"
|
||||
};
|
||||
|
||||
+/*
|
||||
+ * @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,
|
||||
@@ -2246,7 +2261,7 @@ flatpak_run_setup_base_argv (FlatpakBwrap *bwrap,
|
||||
gboolean bwrap_unprivileged = flatpak_bwrap_is_unprivileged ();
|
||||
gsize i;
|
||||
|
||||
- g_return_val_if_fail (runtime_fd >= 0, FALSE);
|
||||
+ g_return_val_if_fail (runtime_fd >= -1, FALSE);
|
||||
|
||||
/* Disable recursive userns for all flatpak processes, as we need this
|
||||
* to guarantee that the sandbox can't restructure the filesystem.
|
||||
@@ -2355,7 +2370,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
|
||||
|
||||
@ -0,0 +1,44 @@
|
||||
From a140dd16297df7dee73bfd6c99c278d7a3fa580c 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 7e8fbf6b..e381b16d 100644
|
||||
--- a/common/flatpak-dir.c
|
||||
+++ b/common/flatpak-dir.c
|
||||
@@ -8476,10 +8476,14 @@ apply_extra_data (FlatpakDir *self,
|
||||
run_flags |= FLATPAK_RUN_FLAG_NO_PROC;
|
||||
|
||||
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,
|
||||
run_flags, error))
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,126 @@
|
||||
From 2bf787c496c8ea0349cee668c90fd52824157a01 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Wick <sebastian.wick@redhat.com>
|
||||
Date: Thu, 21 Aug 2025 18:40:33 +0200
|
||||
Subject: [PATCH] tests: Add test-extra-data.sh to test extra-data installation
|
||||
|
||||
[smcv: Remove OCI test because #3790 was only solved in 1.17.x,
|
||||
only keep libostree test]
|
||||
|
||||
(cherry picked from commit e9e713fa0ddd0d1af4b8cdec6aa9124d471ed33e)
|
||||
---
|
||||
tests/meson.build | 1 +
|
||||
tests/test-extra-data.sh | 63 +++++++++++++++++++++++++++++++++++
|
||||
tests/test-matrix/meson.build | 2 ++
|
||||
tests/update-test-matrix | 1 +
|
||||
4 files changed, 67 insertions(+)
|
||||
create mode 100755 tests/test-extra-data.sh
|
||||
|
||||
diff --git a/tests/meson.build b/tests/meson.build
|
||||
index cb187d71..8f96e5f0 100644
|
||||
--- a/tests/meson.build
|
||||
+++ b/tests/meson.build
|
||||
@@ -362,6 +362,7 @@ foreach testcase : wrapped_tests
|
||||
'test-summaries.sh' : 60,
|
||||
'test-unused.sh' : 90,
|
||||
'test-update-portal.sh' : 90,
|
||||
+ 'test-extra-data.sh' : 90,
|
||||
}.get(script, 30)
|
||||
|
||||
is_parallel = {
|
||||
diff --git a/tests/test-extra-data.sh b/tests/test-extra-data.sh
|
||||
new file mode 100755
|
||||
index 00000000..41c9b913
|
||||
--- /dev/null
|
||||
+++ b/tests/test-extra-data.sh
|
||||
@@ -0,0 +1,63 @@
|
||||
+#!/bin/bash
|
||||
+#
|
||||
+# Copyright (C) 2025 Red Hat, Inc
|
||||
+#
|
||||
+# This library is free software; you can redistribute it and/or
|
||||
+# modify it under the terms of the GNU Lesser General Public
|
||||
+# License as published by the Free Software Foundation; either
|
||||
+# version 2 of the License, or (at your option) any later version.
|
||||
+#
|
||||
+# This library is distributed in the hope that it will be useful,
|
||||
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+# Lesser General Public License for more details.
|
||||
+#
|
||||
+# You should have received a copy of the GNU Lesser General Public
|
||||
+# License along with this library; if not, write to the
|
||||
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
+# Boston, MA 02111-1307, USA.
|
||||
+
|
||||
+set -euo pipefail
|
||||
+
|
||||
+. "$(dirname $0)/libtest.sh"
|
||||
+
|
||||
+skip_without_bwrap
|
||||
+
|
||||
+REPONAME="test"
|
||||
+BRANCH="master"
|
||||
+COLLECTION_ID="org.test.Collection.${REPONAME}"
|
||||
+
|
||||
+setup_repo ${REPONAME} ${COLLECTION_ID}
|
||||
+
|
||||
+# create the extra data
|
||||
+EXTRA_DATA_FILE="extra-data-test"
|
||||
+EXTRA_DATA_DIR="${TEST_DATA_DIR}/extra-data-server/"
|
||||
+mkdir -p "${EXTRA_DATA_DIR}"
|
||||
+echo "extra-data-test-content" > "${EXTRA_DATA_DIR}/${EXTRA_DATA_FILE}"
|
||||
+
|
||||
+# serve the extra data
|
||||
+httpd web-server.py "${EXTRA_DATA_DIR}"
|
||||
+EXTRA_DATA_URL="http://127.0.0.1:$(cat httpd-port)/${EXTRA_DATA_FILE}"
|
||||
+
|
||||
+# download to get the size and sha256 sum
|
||||
+DOWNLOADED_EXTRA_DATA="${TEST_DATA_DIR}/downloaded-extra-data"
|
||||
+curl "${EXTRA_DATA_URL}" -o "${DOWNLOADED_EXTRA_DATA}"
|
||||
+EXTRA_DATA_SIZE=$(stat --printf="%s" "${DOWNLOADED_EXTRA_DATA}")
|
||||
+EXTRA_DATA_SHA256=$(sha256sum "${DOWNLOADED_EXTRA_DATA}" | cut -f1 -d' ')
|
||||
+
|
||||
+echo "1..1"
|
||||
+
|
||||
+# build the app with the extra data
|
||||
+EXTRA_DATA="--extra-data=test:${EXTRA_DATA_SHA256}:${EXTRA_DATA_SIZE}:${EXTRA_DATA_SIZE}:${EXTRA_DATA_URL}"
|
||||
+BUILD_FINISH_ARGS=${EXTRA_DATA} make_updated_app ${REPONAME} ${COLLECTION_ID} ${BRANCH} UPDATE1
|
||||
+
|
||||
+# ensure it installs correctly
|
||||
+install_repo ${REPONAME} ${BRANCH}
|
||||
+
|
||||
+# ensure the right extra-data got downloaded
|
||||
+${FLATPAK} run --command=sh org.test.Hello -c "cat /app/extra/test" > out
|
||||
+assert_file_has_content out "extra-data-test-content"
|
||||
+
|
||||
+${FLATPAK} ${U} uninstall -y org.test.Hello >&2
|
||||
+
|
||||
+ok "install extra data app with ostree"
|
||||
diff --git a/tests/test-matrix/meson.build b/tests/test-matrix/meson.build
|
||||
index ef85b7ec..037500eb 100644
|
||||
--- a/tests/test-matrix/meson.build
|
||||
+++ b/tests/test-matrix/meson.build
|
||||
@@ -29,6 +29,8 @@ wrapped_tests += {'name' : 'test-summaries@user.wrap', 'script' : 'test-summarie
|
||||
wrapped_tests += {'name' : 'test-summaries@system.wrap', 'script' : 'test-summaries.sh'}
|
||||
wrapped_tests += {'name' : 'test-subset@user.wrap', 'script' : 'test-subset.sh'}
|
||||
wrapped_tests += {'name' : 'test-subset@system.wrap', 'script' : 'test-subset.sh'}
|
||||
+wrapped_tests += {'name' : 'test-extra-data@user.wrap', 'script' : 'test-extra-data.sh'}
|
||||
+wrapped_tests += {'name' : 'test-extra-data@system.wrap', 'script' : 'test-extra-data.sh'}
|
||||
wrapped_tests += {'name' : 'test-basic.sh', 'script' : 'test-basic.sh'}
|
||||
wrapped_tests += {'name' : 'test-completion.sh', 'script' : 'test-completion.sh'}
|
||||
wrapped_tests += {'name' : 'test-config.sh', 'script' : 'test-config.sh'}
|
||||
diff --git a/tests/update-test-matrix b/tests/update-test-matrix
|
||||
index 3a51d0ba..2e26a6f2 100755
|
||||
--- a/tests/update-test-matrix
|
||||
+++ b/tests/update-test-matrix
|
||||
@@ -34,6 +34,7 @@ TEST_MATRIX_SOURCE=(
|
||||
'tests/test-prune.sh' \
|
||||
'tests/test-seccomp.sh' \
|
||||
'tests/test-repair.sh' \
|
||||
+ 'tests/test-extra-data.sh{user+system}' \
|
||||
)
|
||||
|
||||
"${tests_srcdir}/expand-test-matrix.sh" --meson "${TEST_MATRIX_SOURCE[*]}" > "${tests_srcdir}/test-matrix/meson.build"
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,121 @@
|
||||
From b9ec9cab240ffdfd8768dc1dd6272d40719ecdcd Mon Sep 17 00:00:00 2001
|
||||
From: bbhtt <bbhtt.zn0i8@slmail.me>
|
||||
Date: Fri, 10 Apr 2026 10:14:23 +0530
|
||||
Subject: [PATCH] tests: Add test for NoRuntime extra-data app
|
||||
|
||||
(cherry picked from commit 79cb10e8803a3f13fe5bd8329dec37e58cfa2a84)
|
||||
---
|
||||
tests/apply-extra-static.c | 15 +++++++++++++
|
||||
tests/meson.build | 15 +++++++++++++
|
||||
tests/test-extra-data.sh | 43 +++++++++++++++++++++++++++++++++++++-
|
||||
3 files changed, 72 insertions(+), 1 deletion(-)
|
||||
create mode 100644 tests/apply-extra-static.c
|
||||
|
||||
diff --git a/tests/apply-extra-static.c b/tests/apply-extra-static.c
|
||||
new file mode 100644
|
||||
index 00000000..5be3993a
|
||||
--- /dev/null
|
||||
+++ b/tests/apply-extra-static.c
|
||||
@@ -0,0 +1,15 @@
|
||||
+#include <sys/stat.h>
|
||||
+#include <fcntl.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+static const char msg[] = "noruntime-extra-data\n";
|
||||
+
|
||||
+int main(void) {
|
||||
+ mkdir("/app/extra", 0755);
|
||||
+ int fd = open("/app/extra/ran", O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
+ if (fd < 0)
|
||||
+ return 1;
|
||||
+ write(fd, msg, sizeof(msg) - 1);
|
||||
+ close(fd);
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/tests/meson.build b/tests/meson.build
|
||||
index 8f96e5f0..464ed0bb 100644
|
||||
--- a/tests/meson.build
|
||||
+++ b/tests/meson.build
|
||||
@@ -291,6 +291,21 @@ executable(
|
||||
install_dir : installed_testdir,
|
||||
)
|
||||
|
||||
+if cc.links('#include <stdio.h>\nint main(void) { printf("test"); return 0; }',
|
||||
+ args: ['-static'],
|
||||
+ name: 'static libc')
|
||||
+ executable(
|
||||
+ 'apply-extra-static',
|
||||
+ 'apply-extra-static.c',
|
||||
+ install : get_option('installed_tests'),
|
||||
+ install_dir : installed_testdir,
|
||||
+ override_options : ['b_sanitize=none'],
|
||||
+ link_args : ['-static'],
|
||||
+ )
|
||||
+else
|
||||
+ warning('static libc not available, apply-extra-static will be skipped')
|
||||
+endif
|
||||
+
|
||||
subdir('share/xdg-desktop-portal/portals')
|
||||
subdir('services')
|
||||
subdir('test-keyring')
|
||||
diff --git a/tests/test-extra-data.sh b/tests/test-extra-data.sh
|
||||
index 41c9b913..73fe3ce9 100755
|
||||
--- a/tests/test-extra-data.sh
|
||||
+++ b/tests/test-extra-data.sh
|
||||
@@ -45,7 +45,7 @@ curl "${EXTRA_DATA_URL}" -o "${DOWNLOADED_EXTRA_DATA}"
|
||||
EXTRA_DATA_SIZE=$(stat --printf="%s" "${DOWNLOADED_EXTRA_DATA}")
|
||||
EXTRA_DATA_SHA256=$(sha256sum "${DOWNLOADED_EXTRA_DATA}" | cut -f1 -d' ')
|
||||
|
||||
-echo "1..1"
|
||||
+echo "1..2"
|
||||
|
||||
# build the app with the extra data
|
||||
EXTRA_DATA="--extra-data=test:${EXTRA_DATA_SHA256}:${EXTRA_DATA_SIZE}:${EXTRA_DATA_SIZE}:${EXTRA_DATA_URL}"
|
||||
@@ -61,3 +61,44 @@ assert_file_has_content out "extra-data-test-content"
|
||||
${FLATPAK} ${U} uninstall -y org.test.Hello >&2
|
||||
|
||||
ok "install extra data app with ostree"
|
||||
+
|
||||
+build_extra_data_noruntime_app() {
|
||||
+ local repo="$1"
|
||||
+ local branch="$2"
|
||||
+
|
||||
+ DIR="$(mktemp -d)"
|
||||
+ ARCH="$(flatpak --default-arch)"
|
||||
+
|
||||
+ mkdir -p "${DIR}/files/bin"
|
||||
+
|
||||
+ cp "${G_TEST_BUILDDIR}/apply-extra-static" "${DIR}/files/bin/apply_extra"
|
||||
+ chmod +x "${DIR}/files/bin/apply_extra"
|
||||
+
|
||||
+ cat > "${DIR}/metadata" <<EOF
|
||||
+[Application]
|
||||
+name=org.test.ExtraDataNoRuntime
|
||||
+runtime=org.test.Platform/${ARCH}/${branch}
|
||||
+
|
||||
+[Extra Data]
|
||||
+NoRuntime=true
|
||||
+uri=${EXTRA_DATA_URL}
|
||||
+size=${EXTRA_DATA_SIZE}
|
||||
+checksum=${EXTRA_DATA_SHA256}
|
||||
+EOF
|
||||
+
|
||||
+ flatpak build-finish "${DIR}" >&2
|
||||
+ flatpak build-export ${FL_GPGARGS} "${repo}" "${DIR}" "${branch}" >&2
|
||||
+ rm -rf "${DIR}"
|
||||
+}
|
||||
+
|
||||
+if test -f "${G_TEST_BUILDDIR}/apply-extra-static"; then
|
||||
+ build_extra_data_noruntime_app repos/test ${BRANCH}
|
||||
+ update_repo ${REPONAME} ${COLLECTION_ID}
|
||||
+ ${FLATPAK} ${U} install --or-update -y ${REPONAME}-repo org.test.ExtraDataNoRuntime ${BRANCH} >&2
|
||||
+ DEPLOY_DIR="$(${FLATPAK} ${U} info --show-location org.test.ExtraDataNoRuntime)"
|
||||
+ assert_file_has_content "${DEPLOY_DIR}/files/extra/ran" "^noruntime-extra-data$"
|
||||
+ ${FLATPAK} ${U} uninstall -y org.test.ExtraDataNoRuntime >&2
|
||||
+ ok "install+run extra data app with NoRuntime"
|
||||
+else
|
||||
+ ok "# SKIP install+run extra data app with NoRuntime apply-extra-static not found"
|
||||
+fi
|
||||
--
|
||||
2.54.0
|
||||
|
||||
52
CVE-2026-34078-26-utils-add-flatpak-set-cloexec.patch
Normal file
52
CVE-2026-34078-26-utils-add-flatpak-set-cloexec.patch
Normal file
@ -0,0 +1,52 @@
|
||||
From 90625f0ef612364ded91a67327bdfe5b59e03b27 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 8f970ea2..e7fa348c 100644
|
||||
--- a/common/flatpak-utils-private.h
|
||||
+++ b/common/flatpak-utils-private.h
|
||||
@@ -353,4 +353,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 7e69e8be..706a9cb2 100644
|
||||
--- a/common/flatpak-utils.c
|
||||
+++ b/common/flatpak-utils.c
|
||||
@@ -2525,3 +2525,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 a58978e40e7650c9c2cda716dd6d387fd6b5ea8e 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 23b9f368..48968fbb 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 b5206aab..5c66a9ee 100644
|
||||
--- a/common/flatpak-context.c
|
||||
+++ b/common/flatpak-context.c
|
||||
@@ -1391,6 +1391,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 ccaf86c854aeed47c2b346666b14e52d0f821b7f 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 f176e884..7d46dd6b 100644
|
||||
--- a/common/flatpak-run.c
|
||||
+++ b/common/flatpak-run.c
|
||||
@@ -2939,42 +2939,6 @@ open_namespace_fd_if_needed (const char *path,
|
||||
return -1;
|
||||
}
|
||||
|
||||
-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,
|
||||
@@ -3203,7 +3167,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,
|
||||
@@ -3331,7 +3295,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");
|
||||
|
||||
@@ -3640,7 +3604,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;
|
||||
|
||||
@@ -3657,7 +3621,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 e7fa348c..8cad6672 100644
|
||||
--- a/common/flatpak-utils-private.h
|
||||
+++ b/common/flatpak-utils-private.h
|
||||
@@ -351,6 +351,9 @@ gboolean flatpak_is_debugging (void);
|
||||
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 706a9cb2..b8bfcfdb 100644
|
||||
--- a/common/flatpak-utils.c
|
||||
+++ b/common/flatpak-utils.c
|
||||
@@ -2542,3 +2542,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 5f73d530a25a119222b42b0680766faba3875777 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 0550a379..be4d40a8 100644
|
||||
--- a/portal/flatpak-portal.c
|
||||
+++ b/portal/flatpak-portal.c
|
||||
@@ -1247,8 +1247,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]);
|
||||
}
|
||||
@@ -1273,8 +1282,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
|
||||
|
||||
94
CVE-2026-34078-3-utils-add-flatpak-parse-fd.patch
Normal file
94
CVE-2026-34078-3-utils-add-flatpak-parse-fd.patch
Normal file
@ -0,0 +1,94 @@
|
||||
From fbe5a2faa776e0f5bdd6160c1dd69b0b97c2d8eb 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 646c5ec5..b5206aab 100644
|
||||
--- a/common/flatpak-context.c
|
||||
+++ b/common/flatpak-context.c
|
||||
@@ -1382,21 +1382,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 7fe509f3..8f970ea2 100644
|
||||
--- a/common/flatpak-utils-private.h
|
||||
+++ b/common/flatpak-utils-private.h
|
||||
@@ -348,6 +348,9 @@ gboolean running_under_sudo_root (void);
|
||||
void flatpak_set_debugging (gboolean debugging);
|
||||
gboolean flatpak_is_debugging (void);
|
||||
|
||||
+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 7bfa2ad1..7a30969c 100644
|
||||
--- a/common/flatpak-utils.c
|
||||
+++ b/common/flatpak-utils.c
|
||||
@@ -2473,3 +2473,25 @@ flatpak_is_debugging (void)
|
||||
|
||||
return is_debugging;
|
||||
}
|
||||
+
|
||||
+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,65 @@
|
||||
From 4b6ee5e5c9ca33638b238c15e865864ed1437fb8 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 be4d40a8..1803dad1 100644
|
||||
--- a/portal/flatpak-portal.c
|
||||
+++ b/portal/flatpak-portal.c
|
||||
@@ -1263,12 +1263,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1298,12 +1295,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 0ef48d4a4bd7479d35c2526104292e36d9ea1500 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 1803dad1..e2f59b73 100644
|
||||
--- a/portal/flatpak-portal.c
|
||||
+++ b/portal/flatpak-portal.c
|
||||
@@ -558,7 +558,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);
|
||||
@@ -577,6 +579,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 b7806fe7838e6a9114163fbcd20c11e7636d695f 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 823b1be2..7004f2d1 100644
|
||||
--- a/tests/libtest.sh
|
||||
+++ b/tests/libtest.sh
|
||||
@@ -312,7 +312,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,61 @@
|
||||
From 4491406f509707feb755982fdda24b2fd9234903 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Wick <sebastian.wick@redhat.com>
|
||||
Date: Fri, 10 Apr 2026 15:44:44 +0200
|
||||
Subject: [PATCH] tests: Check that flatpak-run fd-arguments do not leak to the
|
||||
command
|
||||
|
||||
flatpak-run takes a number of arguments which are file descriptor
|
||||
numbers. Those file descriptors are supposed to set something up in the
|
||||
way the instance gets spawned, but should never make it to the wrapper
|
||||
command.
|
||||
|
||||
(cherry picked from commit 136452768368613f3712c2f7cba79a7c3e7bee96)
|
||||
---
|
||||
tests/test-run-custom.sh | 25 +++++++++++++++++++++++--
|
||||
1 file changed, 23 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/tests/test-run-custom.sh b/tests/test-run-custom.sh
|
||||
index 94c32416..4868b8b5 100755
|
||||
--- a/tests/test-run-custom.sh
|
||||
+++ b/tests/test-run-custom.sh
|
||||
@@ -24,7 +24,7 @@ set -euo pipefail
|
||||
skip_without_bwrap
|
||||
skip_revokefs_without_fuse
|
||||
|
||||
-echo "1..11"
|
||||
+echo "1..12"
|
||||
|
||||
# Use stable rather than master as the branch so we can test that the run
|
||||
# command automatically finds the branch correctly
|
||||
@@ -176,4 +176,25 @@ exec 3< "${path}"
|
||||
! run --ro-bind-fd=3 --command=bash org.test.Hello -c "echo baz > ${path}" > /dev/null
|
||||
exec 3>&-
|
||||
|
||||
-ok "bind-fd and ro-bind-fd"
|
||||
\ No newline at end of file
|
||||
+ok "bind-fd and ro-bind-fd"
|
||||
+
|
||||
+exec 3< custom-app/files
|
||||
+exec 4< custom-runtime/files
|
||||
+exec 5< "${path}"
|
||||
+exec 6< "${path}"
|
||||
+run --app-fd=3 --usr-fd=4 --bind-fd=5 --ro-bind-fd=6 \
|
||||
+ --command=sh org.test.Hello \
|
||||
+ -c 'for fd in $(ls /proc/self/fd); do readlink -f /proc/self/fd/$fd; done' > hello_out
|
||||
+exec 6>&-
|
||||
+exec 5>&-
|
||||
+exec 4>&-
|
||||
+exec 3>&-
|
||||
+
|
||||
+wd="$(readlink -f .)"
|
||||
+while read fdpath; do
|
||||
+ if [[ "$fdpath" == "$wd"* && "$fdpath" != "$wd/hello_out" ]]; then
|
||||
+ assert_not_reached "A fd for '$fdpath' unexpectedly made it to the app"
|
||||
+ fi
|
||||
+done < hello_out
|
||||
+
|
||||
+ok "check no fd leak"
|
||||
\ No newline at end of file
|
||||
--
|
||||
2.54.0
|
||||
|
||||
103
CVE-2026-34078-34-app-context-never-close-fds-0-1-or-2.patch
Normal file
103
CVE-2026-34078-34-app-context-never-close-fds-0-1-or-2.patch
Normal file
@ -0,0 +1,103 @@
|
||||
From 7f5306876adc6f322f88c01801fd5aab2742c7b4 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 48968fbb..f1827a13 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 5c66a9ee..af113946 100644
|
||||
--- a/common/flatpak-context.c
|
||||
+++ b/common/flatpak-context.c
|
||||
@@ -1389,7 +1389,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 817888730861a21bf930f7fbadc28155c2f3de39 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 f1827a13..b6185ca7 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 af113946..59e8d9d4 100644
|
||||
--- a/common/flatpak-context.c
|
||||
+++ b/common/flatpak-context.c
|
||||
@@ -1384,25 +1384,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 8cad6672..75538399 100644
|
||||
--- a/common/flatpak-utils-private.h
|
||||
+++ b/common/flatpak-utils-private.h
|
||||
@@ -358,4 +358,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 b8bfcfdb..09102fd8 100644
|
||||
--- a/common/flatpak-utils.c
|
||||
+++ b/common/flatpak-utils.c
|
||||
@@ -2543,6 +2543,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 5a7e677294c92c04ea8c7c09a2b1abd2988f03df 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 a3d29782..a0eddfd4 100644
|
||||
--- a/common/flatpak-bwrap.c
|
||||
+++ b/common/flatpak-bwrap.c
|
||||
@@ -42,15 +42,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 *
|
||||
@@ -60,9 +51,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,915 @@
|
||||
From 9c9fe3fdf3920428822cacbb249fd75e6d8dbe48 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/flatpak-dir.c | 8 +-
|
||||
common/flatpak-installation.c | 3 +-
|
||||
common/flatpak-run-private.h | 11 +-
|
||||
common/flatpak-run.c | 471 +++++++++++++++++++++++-----------
|
||||
6 files changed, 382 insertions(+), 156 deletions(-)
|
||||
|
||||
diff --git a/app/flatpak-builtins-build.c b/app/flatpak-builtins-build.c
|
||||
index 585f8f4..8625b36 100644
|
||||
--- a/app/flatpak-builtins-build.c
|
||||
+++ b/app/flatpak-builtins-build.c
|
||||
@@ -458,7 +458,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 d0a1fb0..aebc345 100644
|
||||
--- a/app/flatpak-builtins-run.c
|
||||
+++ b/app/flatpak-builtins-run.c
|
||||
@@ -111,6 +111,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;
|
||||
|
||||
run_environ = g_get_environ ();
|
||||
|
||||
@@ -309,14 +311,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/flatpak-dir.c b/common/flatpak-dir.c
|
||||
index 6936d45..a1d71a2 100644
|
||||
--- a/common/flatpak-dir.c
|
||||
+++ b/common/flatpak-dir.c
|
||||
@@ -8468,7 +8468,13 @@ apply_extra_data (FlatpakDir *self,
|
||||
* Disable /proc entirely in this context. */
|
||||
run_flags |= FLATPAK_RUN_FLAG_NO_PROC;
|
||||
|
||||
- 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,
|
||||
run_flags, error))
|
||||
return FALSE;
|
||||
|
||||
diff --git a/common/flatpak-installation.c b/common/flatpak-installation.c
|
||||
index c7d2e1d..00c023f 100644
|
||||
--- a/common/flatpak-installation.c
|
||||
+++ b/common/flatpak-installation.c
|
||||
@@ -703,9 +703,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 40899e2..4c6fe16 100644
|
||||
--- a/common/flatpak-run-private.h
|
||||
+++ b/common/flatpak-run-private.h
|
||||
@@ -30,6 +30,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);
|
||||
|
||||
@@ -71,7 +76,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,
|
||||
@@ -103,12 +108,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_usr_fd,
|
||||
int parent_pid,
|
||||
FlatpakRunFlags flags,
|
||||
const char *cwd,
|
||||
diff --git a/common/flatpak-run.c b/common/flatpak-run.c
|
||||
index 8c92924..3a2028f 100644
|
||||
--- a/common/flatpak-run.c
|
||||
+++ b/common/flatpak-run.c
|
||||
@@ -1609,40 +1609,56 @@ 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;
|
||||
+ const char *tzdir;
|
||||
+ glnx_autofd int tzdir_fd = -1;
|
||||
+ glnx_autofd int zoneinfo_fd = -1;
|
||||
+ g_autoptr(GError) error = NULL;
|
||||
|
||||
- if (runtime_files)
|
||||
- runtime_zoneinfo = g_file_resolve_relative_path (runtime_files, "share/zoneinfo");
|
||||
+ raw_timezone = flatpak_get_timezone ();
|
||||
+ timezone_content = g_strdup_printf ("%s\n", raw_timezone);
|
||||
+ localtime_content = g_strconcat ("../usr/share/zoneinfo/", raw_timezone, NULL);
|
||||
|
||||
- /* Check for runtime /usr/share/zoneinfo */
|
||||
- if (runtime_zoneinfo != NULL && g_file_query_exists (runtime_zoneinfo, NULL))
|
||||
+ tzdir = flatpak_get_tzdir ();
|
||||
+
|
||||
+ tzdir_fd = glnx_chaseat (AT_FDCWD, tzdir, GLNX_CHASE_MUST_BE_DIRECTORY, NULL);
|
||||
+
|
||||
+ zoneinfo_fd = glnx_chaseat (runtime_fd, "share/zoneinfo",
|
||||
+ GLNX_CHASE_RESOLVE_BENEATH |
|
||||
+ GLNX_CHASE_MUST_BE_DIRECTORY,
|
||||
+ NULL);
|
||||
+
|
||||
+ /* Check for host /usr/share/zoneinfo */
|
||||
+ if (tzdir_fd >= 0 && zoneinfo_fd >= 0)
|
||||
+ {
|
||||
+ /* Here we assume the host timezone file exist in the host data */
|
||||
+ flatpak_bwrap_add_args (bwrap,
|
||||
+ "--ro-bind", tzdir, "/usr/share/zoneinfo",
|
||||
+ "--symlink", localtime_content, "/etc/localtime",
|
||||
+ NULL);
|
||||
+ }
|
||||
+ else
|
||||
{
|
||||
- const char *tzdir = flatpak_get_tzdir ();
|
||||
+ g_autofree char *runtime_zoneinfo = NULL;
|
||||
+ glnx_autofd int runtime_zoneinfo_fd = -1;
|
||||
|
||||
- /* Check for host /usr/share/zoneinfo */
|
||||
- if (g_file_test (tzdir, G_FILE_TEST_IS_DIR))
|
||||
+ runtime_zoneinfo = g_strconcat ("share/zoneinfo/", raw_timezone, NULL);
|
||||
+
|
||||
+ /* 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);
|
||||
+ if (runtime_zoneinfo_fd >= 0)
|
||||
{
|
||||
- /* Here we assume the host timezone file exist in the host data */
|
||||
flatpak_bwrap_add_args (bwrap,
|
||||
- "--ro-bind", tzdir, "/usr/share/zoneinfo",
|
||||
"--symlink", localtime_content, "/etc/localtime",
|
||||
NULL);
|
||||
}
|
||||
- else
|
||||
- {
|
||||
- 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_data (bwrap, "timezone",
|
||||
@@ -2138,24 +2154,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_info ("%s does not exist in runtime", subdir);
|
||||
+ }
|
||||
+ else
|
||||
{
|
||||
g_autofree char *link = g_strconcat ("usr", subdir, NULL);
|
||||
g_autofree char *create = NULL;
|
||||
@@ -2169,11 +2202,6 @@ flatpak_run_setup_usr_links (FlatpakBwrap *bwrap,
|
||||
"--symlink", link, create,
|
||||
NULL);
|
||||
}
|
||||
- else
|
||||
- {
|
||||
- g_info ("%s does not exist",
|
||||
- flatpak_file_get_path_cached (runtime_subdir));
|
||||
- }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2189,7 +2217,7 @@ static const char *const sysfs_dirs[] =
|
||||
|
||||
gboolean
|
||||
flatpak_run_setup_base_argv (FlatpakBwrap *bwrap,
|
||||
- GFile *runtime_files,
|
||||
+ int runtime_fd,
|
||||
GFile *app_id_dir,
|
||||
const char *arch,
|
||||
FlatpakRunFlags flags,
|
||||
@@ -2202,12 +2230,13 @@ flatpak_run_setup_base_argv (FlatpakBwrap *bwrap,
|
||||
struct group *g;
|
||||
gulong pers;
|
||||
gid_t gid = getgid ();
|
||||
- g_autoptr(GFile) etc = NULL;
|
||||
gboolean parent_expose_pids = (flags & FLATPAK_RUN_FLAG_PARENT_EXPOSE_PIDS) != 0;
|
||||
gboolean parent_share_pids = (flags & FLATPAK_RUN_FLAG_PARENT_SHARE_PIDS) != 0;
|
||||
gboolean bwrap_unprivileged = flatpak_bwrap_is_unprivileged ();
|
||||
gsize i;
|
||||
|
||||
+ g_return_val_if_fail (runtime_fd >= 0, FALSE);
|
||||
+
|
||||
/* Disable recursive userns for all flatpak processes, as we need this
|
||||
* to guarantee that the sandbox can't restructure the filesystem.
|
||||
* Allowing to change e.g. /.flatpak-info would allow sandbox escape
|
||||
@@ -2315,22 +2344,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;
|
||||
@@ -2347,9 +2379,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;
|
||||
|
||||
@@ -2360,9 +2402,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2383,9 +2428,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;
|
||||
|
||||
@@ -2612,7 +2657,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)
|
||||
@@ -2652,7 +2697,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)
|
||||
{
|
||||
@@ -2867,15 +2912,51 @@ open_namespace_fd_if_needed (const char *path,
|
||||
return -1;
|
||||
}
|
||||
|
||||
+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,
|
||||
@@ -2891,11 +2972,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;
|
||||
@@ -2929,20 +3005,41 @@ 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_assert (run_environ != 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);
|
||||
+
|
||||
/* This check exists to stop accidental usage of `sudo flatpak run`
|
||||
and is not to prevent running as root.
|
||||
*/
|
||||
@@ -3068,38 +3165,53 @@ flatpak_run_app (FlatpakDecomposed *app_ref,
|
||||
|
||||
flatpak_context_dump (app_context, "Final 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);
|
||||
@@ -3186,19 +3298,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;
|
||||
+
|
||||
+ 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 ();
|
||||
+ }
|
||||
|
||||
- /* Mount the original app below here */
|
||||
- app_target_path = "/run/parent/app";
|
||||
+ /* 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)
|
||||
+ {
|
||||
+ use_ld_so_cache = FALSE;
|
||||
}
|
||||
- else if (original_app_files != NULL)
|
||||
+ else
|
||||
{
|
||||
- app_files = g_object_ref (original_app_files);
|
||||
+ 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);
|
||||
@@ -3211,75 +3364,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
|
||||
{
|
||||
@@ -3288,7 +3452,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,
|
||||
@@ -3301,26 +3465,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) */
|
||||
@@ -3332,7 +3507,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)
|
||||
@@ -3342,7 +3517,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
|
||||
|
||||
78
CVE-2026-34078-6-run-add-usr-fd-and-app-fd-options.patch
Normal file
78
CVE-2026-34078-6-run-add-usr-fd-and-app-fd-options.patch
Normal file
@ -0,0 +1,78 @@
|
||||
From 494c5ea687be884487fa5dc8b943130d9df7bb5f 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 aebc345c..a2644f89 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 }
|
||||
};
|
||||
|
||||
@@ -311,7 +315,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)
|
||||
{
|
||||
@@ -330,7 +345,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
|
||||
|
||||
116
CVE-2026-34078-7-run-add-ro-bind-fds-to-flatpak-run-app.patch
Normal file
116
CVE-2026-34078-7-run-add-ro-bind-fds-to-flatpak-run-app.patch
Normal file
@ -0,0 +1,116 @@
|
||||
From 4f1e7f8d1705488e501925255fbe061ac71405fc 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 a2644f89..b14bf056 100644
|
||||
--- a/app/flatpak-builtins-run.c
|
||||
+++ b/app/flatpak-builtins-run.c
|
||||
@@ -385,6 +385,8 @@ flatpak_builtin_run (int argc, char **argv, GCancellable *cancellable, GError **
|
||||
opt_instance_id_fd,
|
||||
(const char * const *) run_environ,
|
||||
NULL,
|
||||
+ NULL,
|
||||
+ NULL,
|
||||
cancellable,
|
||||
error))
|
||||
return FALSE;
|
||||
diff --git a/common/flatpak-installation.c b/common/flatpak-installation.c
|
||||
index 29250b90..fe5e5757 100644
|
||||
--- a/common/flatpak-installation.c
|
||||
+++ b/common/flatpak-installation.c
|
||||
@@ -714,6 +714,7 @@ flatpak_installation_launch_full (FlatpakInstallation *self,
|
||||
NULL, 0, -1,
|
||||
(const char * const *) run_environ,
|
||||
&instance_dir,
|
||||
+ NULL, NULL,
|
||||
cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
diff --git a/common/flatpak-run-private.h b/common/flatpak-run-private.h
|
||||
index 0adbb8af..8c6cc049 100644
|
||||
--- a/common/flatpak-run-private.h
|
||||
+++ b/common/flatpak-run-private.h
|
||||
@@ -124,6 +124,8 @@ gboolean flatpak_run_app (FlatpakDecomposed *app_ref,
|
||||
int instance_id_fd,
|
||||
const char * const *run_environ,
|
||||
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 2813d150..055c721d 100644
|
||||
--- a/common/flatpak-run.c
|
||||
+++ b/common/flatpak-run.c
|
||||
@@ -2979,6 +2979,8 @@ flatpak_run_app (FlatpakDecomposed *app_ref,
|
||||
int instance_id_fd,
|
||||
const char * const *run_environ,
|
||||
char **instance_dir_out,
|
||||
+ GArray *bind_fds,
|
||||
+ GArray *ro_bind_fds,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
@@ -3583,6 +3585,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
CVE-2026-34078-8-run-add-ro-bind-fd-options.patch
Normal file
95
CVE-2026-34078-8-run-add-ro-bind-fd-options.patch
Normal file
@ -0,0 +1,95 @@
|
||||
From a971671f9546a20e2134afde31b317ff140e5bd9 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 b14bf056..0bfc311d 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 }
|
||||
};
|
||||
|
||||
@@ -120,6 +162,9 @@ flatpak_builtin_run (int argc, char **argv, GCancellable *cancellable, GError **
|
||||
|
||||
run_environ = g_get_environ ();
|
||||
|
||||
+ 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);
|
||||
|
||||
@@ -385,8 +430,8 @@ flatpak_builtin_run (int argc, char **argv, GCancellable *cancellable, GError **
|
||||
opt_instance_id_fd,
|
||||
(const char * const *) run_environ,
|
||||
NULL,
|
||||
- NULL,
|
||||
- NULL,
|
||||
+ opt_bind_fds,
|
||||
+ opt_ro_bind_fds,
|
||||
cancellable,
|
||||
error))
|
||||
return FALSE;
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -0,0 +1,602 @@
|
||||
From c82a3d7716bd02961d8c68b1d18256dfea19efc5 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 12f2729a..5c0935a1 100644
|
||||
--- a/portal/flatpak-portal.c
|
||||
+++ b/portal/flatpak-portal.c
|
||||
@@ -552,195 +552,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
|
||||
@@ -798,10 +663,13 @@ 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_autofree char *app_id_prefix = NULL;
|
||||
+ 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;
|
||||
@@ -925,29 +793,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_info ("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_info ("exposing %s", expose);
|
||||
- if (!is_valid_expose (expose, &error))
|
||||
- {
|
||||
- g_dbus_method_invocation_return_gerror (invocation, error);
|
||||
- return G_DBUS_METHOD_INVOCATION_HANDLED;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
app_id_prefix = g_strdup_printf ("%s.", app_id);
|
||||
for (i = 0; sandbox_a11y_own_names != NULL && sandbox_a11y_own_names[i] != NULL; i++)
|
||||
{
|
||||
@@ -1197,10 +1042,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,
|
||||
@@ -1211,16 +1060,12 @@ handle_spawn (PortalFlatpak *object,
|
||||
}
|
||||
|
||||
env_fd = g_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++)
|
||||
@@ -1318,54 +1163,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_info ("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_info ("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;
|
||||
}
|
||||
@@ -1375,31 +1266,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_info ("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",
|
||||
@@ -1409,20 +1289,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)
|
||||
{
|
||||
@@ -1434,18 +1334,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_info ("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)
|
||||
{
|
||||
@@ -1454,8 +1347,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)
|
||||
{
|
||||
@@ -1467,18 +1360,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_info ("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,84 @@
|
||||
From c97905c8188ddaad01ee146b57bba6c3fa294113 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Wick <sebastian.wick@redhat.com>
|
||||
Date: Fri, 9 Jan 2026 19:24:44 +0100
|
||||
Subject: 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 FIXME)
|
||||
|
||||
diff --git a/common/flatpak-utils.c b/common/flatpak-utils.c
|
||||
index 7a30969c..dbc46951 100644
|
||||
--- a/common/flatpak-utils.c
|
||||
+++ b/common/flatpak-utils.c
|
||||
@@ -922,6 +922,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
|
||||
@@ -931,6 +947,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,
|
||||
@@ -974,10 +993,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)
|
||||
@ -0,0 +1,50 @@
|
||||
From 4a678f463b455c585d38ac4cf4d994e7ce710f8e 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 FIXME)
|
||||
---
|
||||
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 f45cec5c..942bb47b 100644
|
||||
--- a/common/flatpak-oci-registry.c
|
||||
+++ b/common/flatpak-oci-registry.c
|
||||
@@ -275,6 +275,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,
|
||||
@@ -286,7 +289,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,150 @@
|
||||
From a27ec46e8c0ab0ae162f2aa3142dccb6b79d9211 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.
|
||||
---
|
||||
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 778b3c59..f709f948 100644
|
||||
--- a/system-helper/flatpak-system-helper.c
|
||||
+++ b/system-helper/flatpak-system-helper.c
|
||||
@@ -358,23 +358,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);
|
||||
@@ -426,6 +434,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,
|
||||
@@ -433,30 +444,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,
|
||||
@@ -738,31 +736,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
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
From 5f5aeea8d8be071468fb8e9640554518fb65885e Mon Sep 17 00:00:00 2001
|
||||
From 8c8d6faa9f0fc35581e95a9e771490feb94dd9ac Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Wick <sebastian.wick@redhat.com>
|
||||
Date: Tue, 16 Dec 2025 17:15:32 +0100
|
||||
Subject: [PATCH] run: Enable FIPS crypto policy if it is enabled on the host
|
||||
@ -6,27 +6,30 @@ Subject: [PATCH] run: Enable FIPS crypto policy if it is enabled on the host
|
||||
This is a close copy of what podman/containers does to support FIPS. Any
|
||||
other crypto policy is ignored for now.
|
||||
---
|
||||
common/flatpak-run.c | 87 ++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 87 insertions(+)
|
||||
common/flatpak-run.c | 94 ++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 94 insertions(+)
|
||||
|
||||
diff --git ./common/flatpak-run.c ../common/flatpak-run.c
|
||||
index 6c319231..b51cc637 100644
|
||||
--- ./common/flatpak-run.c
|
||||
+++ ../common/flatpak-run.c
|
||||
@@ -2215,6 +2215,91 @@ flatpak_run_setup_usr_links (FlatpakBwrap *bwrap,
|
||||
diff --git a/common/flatpak-run.c b/common/flatpak-run.c
|
||||
index dfcef03..121bef3 100644
|
||||
--- a/common/flatpak-run.c
|
||||
+++ b/common/flatpak-run.c
|
||||
@@ -2214,6 +2214,98 @@ flatpak_run_setup_usr_links (FlatpakBwrap *bwrap,
|
||||
}
|
||||
}
|
||||
|
||||
+static void
|
||||
+flatpak_run_setup_fips (FlatpakBwrap *bwrap,
|
||||
+ GFile *runtime_files)
|
||||
+ int runtime_fd)
|
||||
+{
|
||||
+ g_autoptr(GFile) runtime_crypto_policies = NULL;
|
||||
+ g_autoptr(GFile) runtime_fips_backend = NULL;
|
||||
+ g_autoptr(GFile) runtime_fips_config = NULL;
|
||||
+ glnx_autofd int crypto_policies_fd = -1;
|
||||
+ glnx_autofd int fips_backend_fd = -1;
|
||||
+ glnx_autofd int fips_config_fd = -1;
|
||||
+ g_autofree char *fips_enabled = NULL;
|
||||
+ g_autoptr(GError) error = NULL;
|
||||
+
|
||||
+ if (runtime_fd < 0)
|
||||
+ return;
|
||||
+
|
||||
+ if (!g_file_get_contents ("/proc/sys/crypto/fips_enabled",
|
||||
+ &fips_enabled,
|
||||
+ NULL, &error))
|
||||
@ -48,35 +51,39 @@ index 6c319231..b51cc637 100644
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ runtime_crypto_policies =
|
||||
+ g_file_resolve_relative_path (runtime_files, "etc/crypto-policies");
|
||||
+ crypto_policies_fd = glnx_chaseat (runtime_fd, "etc/crypto-policies",
|
||||
+ GLNX_CHASE_RESOLVE_BENEATH,
|
||||
+ NULL);
|
||||
+
|
||||
+ if (!g_file_query_exists (runtime_crypto_policies, NULL))
|
||||
+ if (crypto_policies_fd < 0)
|
||||
+ {
|
||||
+ g_info ("FIPS is enabled, but runtime does not support it");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ runtime_fips_backend =
|
||||
+ g_file_resolve_relative_path (runtime_files,
|
||||
+ "share/crypto-policies/back-ends/FIPS");
|
||||
+ fips_backend_fd = glnx_chaseat (runtime_fd,
|
||||
+ "share/crypto-policies/back-ends/FIPS",
|
||||
+ GLNX_CHASE_RESOLVE_BENEATH,
|
||||
+ NULL);
|
||||
+
|
||||
+ if (!g_file_query_exists (runtime_fips_backend, NULL))
|
||||
+ if (fips_backend_fd < 0)
|
||||
+ {
|
||||
+ g_info ("FIPS is enabled, but runtime does not support it");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ runtime_fips_config =
|
||||
+ g_file_resolve_relative_path (runtime_files,
|
||||
+ "share/crypto-policies/default-fips-config");
|
||||
+ fips_config_fd = glnx_chaseat (runtime_fd,
|
||||
+ "share/crypto-policies/default-fips-config",
|
||||
+ GLNX_CHASE_RESOLVE_BENEATH |
|
||||
+ GLNX_CHASE_MUST_BE_REGULAR,
|
||||
+ NULL);
|
||||
+
|
||||
+ if (g_file_query_exists (runtime_fips_config, NULL))
|
||||
+ if (fips_config_fd >= 0)
|
||||
+ {
|
||||
+ flatpak_bwrap_add_args (bwrap, "--ro-bind",
|
||||
+ flatpak_file_get_path_cached (runtime_fips_config),
|
||||
+ "/etc/crypto-policies/config",
|
||||
+ NULL);
|
||||
+ flatpak_bwrap_add_args_data_fd (bwrap,
|
||||
+ "--ro-bind-fd",
|
||||
+ g_steal_fd (&fips_config_fd),
|
||||
+ "/etc/crypto-policies/config");
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
@ -94,10 +101,10 @@ index 6c319231..b51cc637 100644
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ flatpak_bwrap_add_args (bwrap, "--ro-bind",
|
||||
+ flatpak_file_get_path_cached (runtime_fips_backend),
|
||||
+ "/etc/crypto-policies/back-ends",
|
||||
+ NULL);
|
||||
+ flatpak_bwrap_add_args_data_fd (bwrap,
|
||||
+ "--ro-bind-fd",
|
||||
+ g_steal_fd (&fips_backend_fd),
|
||||
+ "/etc/crypto-policies/back-ends");
|
||||
+
|
||||
+ g_info ("Enabled FIPS configuration");
|
||||
+}
|
||||
@ -105,15 +112,15 @@ index 6c319231..b51cc637 100644
|
||||
/* Directories in /sys to share with the sandbox if accessible. */
|
||||
static const char *const sysfs_dirs[] =
|
||||
{
|
||||
@@ -2405,6 +2490,8 @@ flatpak_run_setup_base_argv (FlatpakBwrap *bwrap,
|
||||
@@ -2426,6 +2518,8 @@ flatpak_run_setup_base_argv (FlatpakBwrap *bwrap,
|
||||
}
|
||||
}
|
||||
|
||||
+ flatpak_run_setup_fips (bwrap, runtime_files);
|
||||
+ flatpak_run_setup_fips (bwrap, runtime_fd);
|
||||
+
|
||||
if (app_id_dir != NULL)
|
||||
{
|
||||
g_autoptr(GFile) app_cache_dir = g_file_get_child (app_id_dir, "cache");
|
||||
--
|
||||
2.51.0
|
||||
2.54.0
|
||||
|
||||
|
||||
50
flatpak.spec
50
flatpak.spec
@ -12,7 +12,7 @@
|
||||
|
||||
Name: flatpak
|
||||
Version: 1.16.0
|
||||
Release: 9%{?dist}
|
||||
Release: 9%{?dist}.1
|
||||
Summary: Application deployment framework for desktop apps
|
||||
|
||||
License: LGPL-2.1-or-later
|
||||
@ -52,6 +52,48 @@ Patch7: flatpak-run-Enable-FIPS-crypto-policy-if-it-is-enabled-on-th.pat
|
||||
# Stop killing the session when stopping background apps
|
||||
Patch9: flatpak-kill-Do-not-kill-pid-0-and-embrace-races.patch
|
||||
|
||||
# CVE-2026-34078
|
||||
Patch100: CVE-2026-34078-1-update-subtree-libglnx-2026-04-07.patch
|
||||
Patch101: CVE-2026-34078-2-flatpak-bwrap-add-dup-ing-variant-flatpak-bwrap-add-args-data-fd-dup.patch
|
||||
Patch102: CVE-2026-34078-3-utils-add-flatpak-parse-fd.patch
|
||||
Patch103: CVE-2026-34078-4-flatpak-bwrap-use-glnx-close-fd-as-clear-func.patch
|
||||
Patch104: CVE-2026-34078-5-run-use-o-path-fds-for-the-runtime-and-app-deploy-directories.patch
|
||||
Patch105: CVE-2026-34078-6-run-add-usr-fd-and-app-fd-options.patch
|
||||
Patch106: CVE-2026-34078-7-run-add-ro-bind-fds-to-flatpak-run-app.patch
|
||||
Patch107: CVE-2026-34078-8-run-add-ro-bind-fd-options.patch
|
||||
Patch108: CVE-2026-34078-9-portal-use-bind-fd-app-fd-and-usr-fd-options-to-avoid-races.patch
|
||||
Patch109: CVE-2026-34078-10-run-fix-checking-wrong-variable-in-runtime-fd-selection.patch
|
||||
Patch110: CVE-2026-34078-11-run-mount-original-app-on-run-parent-app-when-using-app-path.patch
|
||||
Patch111: CVE-2026-34078-12-portal-update-max-fd-after-creating-the-instance-id-pipe.patch
|
||||
Patch112: CVE-2026-34078-13-run-fix-fd-tracking-in-flatpak-run-add-app-info-args.patch
|
||||
Patch113: CVE-2026-34078-14-utils-improve-error-message-when-passing-an-fd-numer-which-is-not-a-fd.patch
|
||||
Patch114: CVE-2026-34078-15-run-do-not-close-bind-ro-bind.patch
|
||||
Patch115: CVE-2026-34078-16-run-use-the-same-fd-validation-for-all-fd-options.patch
|
||||
Patch116: CVE-2026-34078-17-run-add-bind-fd-and-ro-bind-fd-binds-after-all-other-binds.patch
|
||||
Patch117: CVE-2026-34078-18-portal-use-g-array-index-to-read-from-expose-fds-expose-fds-ro.patch
|
||||
Patch118: CVE-2026-34078-19-run-fix-backport-mistake.patch
|
||||
Patch119: CVE-2026-34078-20-tests-test-run-custom-test-usr-path-usr-fd-app-path-app-fd.patch
|
||||
Patch120: CVE-2026-34078-21-tests-test-run-custom-test-bind-fd-and-ro-bind-fd.patch
|
||||
Patch121: CVE-2026-34078-22-run-cope-with-an-empty-runtime.patch
|
||||
Patch122: CVE-2026-34078-23-dir-in-apply-extra-data-don-t-assume-there-is-always-a-runtime.patch
|
||||
Patch123: CVE-2026-34078-24-tests-add-test-extra-data-sh-to-test-extra-data-installation.patch
|
||||
Patch124: CVE-2026-34078-25-tests-add-test-for-noruntime-extra-data-app.patch
|
||||
Patch125: CVE-2026-34078-26-utils-add-flatpak-set-cloexec.patch
|
||||
Patch126: CVE-2026-34078-27-run-context-mark-fd-arguments-as-close-on-exec.patch
|
||||
Patch127: CVE-2026-34078-28-utils-move-flatpak-get-path-for-fd-to-here.patch
|
||||
Patch128: CVE-2026-34078-29-portal-avoid-crash-if-sandbox-expose-ro-fd-is-out-of-range.patch
|
||||
Patch129: CVE-2026-34078-30-portal-log-and-ignore-unusable-sandbox-expose-fds-instead-of-erroring.patch
|
||||
Patch130: CVE-2026-34078-31-portal-reinstate-flatpak-get-path-for-fd-checks.patch
|
||||
Patch131: CVE-2026-34078-32-libtest-allow-adding-a-new-ref-to-an-existing-temporary-ostree-repo.patch
|
||||
Patch132: CVE-2026-34078-33-tests-check-that-flatpak-run-fd-arguments-do-not-leak-to-the-command.patch
|
||||
Patch133: CVE-2026-34078-34-app-context-never-close-fds-0-1-or-2.patch
|
||||
Patch134: CVE-2026-34078-35-app-context-factor-out-flatpak-accept-fd-argument.patch
|
||||
|
||||
# CVE-2026-34079
|
||||
Patch135: CVE-2026-34079-1-utils-only-remove-cached-files-in-the-cache-directory.patch
|
||||
Patch136: CVE-2026-34079-2-utils-do-not-follow-symlinks-in-local-open-file.patch
|
||||
Patch137: CVE-2026-34079-3-system-helper-only-remove-an-ongoing-pull-if-users-match.patch
|
||||
|
||||
# ostree not on i686 for RHEL 10
|
||||
# https://github.com/containers/composefs/pull/229#issuecomment-1838735764
|
||||
%if 0%{?rhel} >= 10
|
||||
@ -320,6 +362,12 @@ fi
|
||||
|
||||
|
||||
%changelog
|
||||
* Mon May 18 2026 Jan Grulich <jgrulich@redhat.com> - 1.16.0-9.1
|
||||
- Fix arbitrary code execution via crafted symlinks in sandbox-expose options
|
||||
Resolves: RHEL-165630
|
||||
- Fix arbitrary file deletion on host via improper cache file path validation
|
||||
Resolves: RHEL-170157
|
||||
|
||||
* Tue Jan 13 2026 Sebastian Wick <sebastian.wick@redhat.com> - 1.16.0-9
|
||||
- kill: Do not kill pid 0 and embrace races
|
||||
Resolves: RHEL-140924
|
||||
|
||||
Loading…
Reference in New Issue
Block a user