mirror of
https://github.com/flatpak/flatpak.git
synced 2026-10-06 12:59:38 -04:00
run: Harden ensure_data_dir and /var setup against symlink attacks
Replace path-based flatpak_mkdir_p calls in flatpak_ensure_data_dir with glnx_chase_and_mkdirat(RESOLVE_NO_SYMLINKS) to prevent an app from replacing subdirectories of its data dir with symlinks between runs and having them followed during the next sandbox setup. In flatpak_run_setup_base_argv, replace path-based --bind args for the app cache/data/config/tmp directories with --bind-fd using fds obtained via glnx_chaseat(RESOLVE_NO_SYMLINKS), preventing both symlink following and TOCTOU races when setting up these bind mounts. Assisted-by: Claude:opus-4.6 Resolves: https://github.com/flatpak/flatpak/security/advisories/GHSA-8688-9x26-hhxj
This commit is contained in:
1 parent
2beb8890dc
commit
924bdc9b3d
1 file changed
+57
-31
+57
-31
@@ -857,30 +857,35 @@ flatpak_ensure_data_dir (GFile *app_id_dir,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GFile) data_dir = g_file_get_child (app_id_dir, "data");
|
||||
g_autoptr(GFile) cache_dir = g_file_get_child (app_id_dir, "cache");
|
||||
g_autoptr(GFile) fontconfig_cache_dir = g_file_get_child (cache_dir, "fontconfig");
|
||||
g_autoptr(GFile) tmp_dir = g_file_get_child (cache_dir, "tmp");
|
||||
g_autoptr(GFile) config_dir = g_file_get_child (app_id_dir, "config");
|
||||
g_autoptr(GFile) state_dir = g_file_get_child (app_id_dir, ".local/state");
|
||||
glnx_autofd int app_id_dir_fd = -1;
|
||||
static const char *const subdirs[] = {
|
||||
"data",
|
||||
"cache",
|
||||
"cache/fontconfig",
|
||||
"cache/tmp",
|
||||
"config",
|
||||
".local/state",
|
||||
};
|
||||
|
||||
if (!flatpak_mkdir_p (data_dir, cancellable, error))
|
||||
app_id_dir_fd = glnx_chase_and_mkdirat (AT_FDCWD,
|
||||
flatpak_file_get_path_cached (app_id_dir),
|
||||
GLNX_CHASE_DEFAULT,
|
||||
0755,
|
||||
error);
|
||||
if (app_id_dir_fd < 0)
|
||||
return FALSE;
|
||||
|
||||
if (!flatpak_mkdir_p (cache_dir, cancellable, error))
|
||||
return FALSE;
|
||||
for (size_t i = 0; i < G_N_ELEMENTS (subdirs); i++)
|
||||
{
|
||||
glnx_autofd int fd = -1;
|
||||
|
||||
if (!flatpak_mkdir_p (fontconfig_cache_dir, cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
if (!flatpak_mkdir_p (tmp_dir, cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
if (!flatpak_mkdir_p (config_dir, cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
if (!flatpak_mkdir_p (state_dir, cancellable, error))
|
||||
return FALSE;
|
||||
fd = glnx_chase_and_mkdirat (app_id_dir_fd, subdirs[i],
|
||||
GLNX_CHASE_RESOLVE_BENEATH,
|
||||
0755,
|
||||
error);
|
||||
if (fd < 0)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -2526,18 +2531,39 @@ flatpak_run_setup_base_argv (FlatpakBwrap *bwrap,
|
||||
|
||||
if (app_id_dir != NULL)
|
||||
{
|
||||
g_autoptr(GFile) app_cache_dir = g_file_get_child (app_id_dir, "cache");
|
||||
g_autoptr(GFile) app_tmp_dir = g_file_get_child (app_cache_dir, "tmp");
|
||||
g_autoptr(GFile) app_data_dir = g_file_get_child (app_id_dir, "data");
|
||||
g_autoptr(GFile) app_config_dir = g_file_get_child (app_id_dir, "config");
|
||||
glnx_autofd int app_id_dir_fd = -1;
|
||||
static const struct
|
||||
{
|
||||
const char *src;
|
||||
const char *dst;
|
||||
}
|
||||
mounts[] = {
|
||||
{ "cache", "/var/cache" },
|
||||
{ "data", "/var/data" },
|
||||
{ "config", "/var/config" },
|
||||
{ "cache/tmp", "/var/tmp" },
|
||||
};
|
||||
|
||||
flatpak_bwrap_add_args (bwrap,
|
||||
/* These are nice to have as a fixed path */
|
||||
"--bind", flatpak_file_get_path_cached (app_cache_dir), "/var/cache",
|
||||
"--bind", flatpak_file_get_path_cached (app_data_dir), "/var/data",
|
||||
"--bind", flatpak_file_get_path_cached (app_config_dir), "/var/config",
|
||||
"--bind", flatpak_file_get_path_cached (app_tmp_dir), "/var/tmp",
|
||||
NULL);
|
||||
app_id_dir_fd = glnx_chaseat (AT_FDCWD,
|
||||
flatpak_file_get_path_cached (app_id_dir),
|
||||
GLNX_CHASE_MUST_BE_DIRECTORY,
|
||||
error);
|
||||
if (app_id_dir_fd < 0)
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (mounts); i++)
|
||||
{
|
||||
glnx_autofd int fd = -1;
|
||||
|
||||
fd = glnx_chase_and_mkdirat (app_id_dir_fd, mounts[i].src,
|
||||
GLNX_CHASE_RESOLVE_BENEATH,
|
||||
0755, error);
|
||||
if (fd < 0)
|
||||
return FALSE;
|
||||
|
||||
flatpak_bwrap_add_args_data_fd (bwrap, "--bind-fd",
|
||||
g_steal_fd (&fd), mounts[i].dst);
|
||||
}
|
||||
}
|
||||
|
||||
flatpak_run_setup_usr_links (bwrap, runtime_fd, NULL);
|
||||
|
||||
Reference in new issue
Block a user