diff options
author | Alexander Larsson <alexl@redhat.com> | 2020-06-22 12:27:19 +0200 |
---|---|---|
committer | Alexander Larsson <alexander.larsson@gmail.com> | 2020-06-23 09:37:30 +0200 |
commit | dc4e198766d91aa8871c276b9ed8d7f3ba003822 (patch) | |
tree | 3db21e244b353931608d4e159d04964b47c708eb | |
parent | 5a646117c9ec5357c55bc3d196e05a47aa409c66 (diff) | |
download | flatpak-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.c | 89 | ||||
-rw-r--r-- | common/flatpak-utils-base.c | 18 |
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, |