summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2020-06-22 12:27:19 +0200
committerAlexander Larsson <alexander.larsson@gmail.com>2020-06-23 09:37:30 +0200
commitdc4e198766d91aa8871c276b9ed8d7f3ba003822 (patch)
tree3db21e244b353931608d4e159d04964b47c708eb
parent5a646117c9ec5357c55bc3d196e05a47aa409c66 (diff)
downloadflatpak-dc4e198766d91aa8871c276b9ed8d7f3ba003822.tar.gz
run: Always expose host /usr/share/zoneinfo (if possible)
Instead of relying on the runtime tzdate we now always expose the host /usr/share/zoneinfo in that location and make /etc/localtime a regular symlink to it. This means applications that parse the content of the localtime symlink will work, and additionally it means that we're guaranteed that the host configure timezone exists (and works with) the tzdata in the app. This unfortunately means we no longer make the localtime an indirect file via the session helper, and thus that localtime configurations are static over the lifetime of an app sandbox. However, I don't think there is a workable solution to this. This fixes https://github.com/flatpak/flatpak/issues/3338
-rw-r--r--common/flatpak-run.c89
-rw-r--r--common/flatpak-utils-base.c18
2 files changed, 56 insertions, 51 deletions
diff --git a/common/flatpak-run.c b/common/flatpak-run.c
index 6e8b9451..de805cf7 100644
--- a/common/flatpak-run.c
+++ b/common/flatpak-run.c
@@ -2417,6 +2417,47 @@ flatpak_run_add_app_info_args (FlatpakBwrap *bwrap,
}
static void
+add_tzdata_args (FlatpakBwrap *bwrap,
+ GFile *runtime_files)
+{
+ g_autofree char *timezone = flatpak_get_timezone ();
+ g_autofree char *timezone_content = g_strdup_printf ("%s\n", timezone);
+ g_autofree char *localtime_content = g_strconcat ("../usr/share/zoneinfo/", timezone, NULL);
+ g_autoptr(GFile) runtime_zoneinfo = NULL;
+
+ if (runtime_files)
+ runtime_zoneinfo = g_file_resolve_relative_path (runtime_files, "share/zoneinfo");
+
+ /* Check for runtime /usr/share/zoneinfo */
+ if (runtime_zoneinfo != NULL && g_file_query_exists (runtime_zoneinfo, NULL))
+ {
+ /* Check for host /usr/share/zoneinfo */
+ if (g_file_test ("/usr/share/zoneinfo", G_FILE_TEST_IS_DIR))
+ {
+ /* Here we assume the host timezone file exist in the host data */
+ flatpak_bwrap_add_args (bwrap,
+ "--ro-bind", "/usr/share/zoneinfo", "/usr/share/zoneinfo",
+ "--symlink", localtime_content, "/etc/localtime",
+ NULL);
+ }
+ else
+ {
+ g_autoptr(GFile) runtime_tzfile = g_file_resolve_relative_path (runtime_zoneinfo, 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",
+ timezone_content, -1, "/etc/timezone",
+ NULL);
+}
+
+static void
add_monitor_path_args (gboolean use_session_helper,
FlatpakBwrap *bwrap)
{
@@ -2443,11 +2484,9 @@ add_monitor_path_args (gboolean use_session_helper,
if (g_variant_lookup (session_data, "path", "s", &monitor_path))
flatpak_bwrap_add_args (bwrap,
"--ro-bind", monitor_path, "/run/host/monitor",
- "--symlink", "/run/host/monitor/localtime", "/etc/localtime",
"--symlink", "/run/host/monitor/resolv.conf", "/etc/resolv.conf",
"--symlink", "/run/host/monitor/host.conf", "/etc/host.conf",
"--symlink", "/run/host/monitor/hosts", "/etc/hosts",
- "--symlink", "/run/host/monitor/timezone", "/etc/timezone",
NULL);
if (g_variant_lookup (session_data, "pkcs11-socket", "s", &pkcs11_socket_path))
@@ -2470,50 +2509,6 @@ add_monitor_path_args (gboolean use_session_helper,
}
else
{
- /* /etc/localtime and /etc/resolv.conf can not exist (or be symlinks to
- * non-existing targets), in which case we don't want to attempt to create
- * bogus symlinks or bind mounts, as that will cause flatpak run to fail.
- */
- if (g_file_test ("/etc/localtime", G_FILE_TEST_EXISTS))
- {
- g_autofree char *localtime = NULL;
- gboolean is_reachable = FALSE;
- g_autofree char *timezone = flatpak_get_timezone ();
- g_autofree char *timezone_content = g_strdup_printf ("%s\n", timezone);
-
- localtime = glnx_readlinkat_malloc (-1, "/etc/localtime", NULL, NULL);
-
- if (localtime != NULL)
- {
- g_autoptr(GFile) base_file = NULL;
- g_autoptr(GFile) target_file = NULL;
- g_autofree char *target_canonical = NULL;
-
- base_file = g_file_new_for_path ("/etc");
- target_file = g_file_resolve_relative_path (base_file, localtime);
- target_canonical = g_file_get_path (target_file);
-
- is_reachable = g_str_has_prefix (target_canonical, "/usr/");
- }
-
- if (is_reachable)
- {
- flatpak_bwrap_add_args (bwrap,
- "--symlink", localtime, "/etc/localtime",
- NULL);
- }
- else
- {
- flatpak_bwrap_add_args (bwrap,
- "--ro-bind", "/etc/localtime", "/etc/localtime",
- NULL);
- }
-
- flatpak_bwrap_add_args_data (bwrap, "timezone",
- timezone_content, -1, "/etc/timezone",
- NULL);
- }
-
if (g_file_test ("/etc/resolv.conf", G_FILE_TEST_EXISTS))
flatpak_bwrap_add_args (bwrap,
"--ro-bind", "/etc/resolv.conf", "/etc/resolv.conf",
@@ -3020,6 +3015,8 @@ flatpak_run_setup_base_argv (FlatpakBwrap *bwrap,
flatpak_run_setup_usr_links (bwrap, runtime_files);
+ add_tzdata_args (bwrap, runtime_files);
+
pers = PER_LINUX;
if ((flags & FLATPAK_RUN_FLAG_SET_PERSONALITY) &&
diff --git a/common/flatpak-utils-base.c b/common/flatpak-utils-base.c
index ccb5de66..ac636071 100644
--- a/common/flatpak-utils-base.c
+++ b/common/flatpak-utils-base.c
@@ -34,10 +34,7 @@ flatpak_get_timezone (void)
g_autofree gchar *symlink = NULL;
gchar *etc_timezone = NULL;
const gchar *tzdir;
-
- tzdir = getenv ("TZDIR");
- if (tzdir == NULL)
- tzdir = "/usr/share/zoneinfo";
+ const gchar *default_tzdir = "/usr/share/zoneinfo";
symlink = flatpak_resolve_link ("/etc/localtime", NULL);
if (symlink != NULL)
@@ -47,7 +44,9 @@ flatpak_get_timezone (void)
char *canonical_suffix;
/* Strip the prefix and slashes if possible. */
- if (g_str_has_prefix (canonical, tzdir))
+
+ tzdir = getenv ("TZDIR");
+ if (tzdir != NULL && g_str_has_prefix (canonical, tzdir))
{
canonical_suffix = canonical + strlen (tzdir);
while (*canonical_suffix == '/')
@@ -55,6 +54,15 @@ flatpak_get_timezone (void)
return g_strdup (canonical_suffix);
}
+
+ if (g_str_has_prefix (canonical, default_tzdir))
+ {
+ canonical_suffix = canonical + strlen (default_tzdir);
+ while (*canonical_suffix == '/')
+ canonical_suffix++;
+
+ return g_strdup (canonical_suffix);
+ }
}
if (g_file_get_contents ("/etc/timezone", &etc_timezone,