Package: release.debian.org Severity: normal User: release.debian....@packages.debian.org Usertags: unblock
Please unblock package flatpak. This is a new upstream stable release; notably, it includes use-after-free and memory leak fixes in the D-Bus proxy (which is a security boundary), and protects against accidental or malicious downgrades. Filtered debdiff attached. The vast majority of the debdiff is accounted for by the fixes mentioned above; the rest is described in the changelog below. unblock flatpak/0.8.5-1 flatpak (0.8.5-1) unstable; urgency=medium * New upstream bugfix release * Upstream security fixes: - dbus-proxy: Fix a use-after-free (no specific exploit is known) and several memory leaks - system-helper: Correct the check that was meant to prevent unprivileged users from downgrading system-wide-installed apps - Do not allow downgrading apps to validly-signed older versions unless a specific older version is requested, so that a man-in-the-middle cannot cause a downgrade to an older app version with a vulnerability * Other upstream fixes: - Increase GLib build-dependency to 2.44 (in practice this was already required, there is a patch in jessie-backports to relax this) - Collect system extension references from all system directories, not just the first that exists (upstream issue 654) - Stop using ostree trivial-httpd, which is not available in post-stretch ostree (upstream issues 658, 723) - Be build-time compatible with post-stretch ostree (upstream issue 756) - Strip ?query suffix before detecting whether a URI points to a .flatpakref or .flatpakrepo file (upstream issue 659) - Fix a typo in help output * d/tests/control: most tests now require python, for the ostree-trivial-httpd replacement -- Simon McVittie <s...@debian.org> Mon, 03 Apr 2017 16:35:44 +0100 Thanks, S
diffstat for flatpak-0.8.4 flatpak-0.8.5 NEWS | 30 ++++ app/flatpak-builtins-add-remote.c | 2 app/flatpak-builtins-install.c | 4 app/flatpak-builtins-update.c | 2 common/flatpak-dir.c | 49 ++++++- common/flatpak-dir.h | 1 common/flatpak-utils.c | 49 +++---- common/flatpak-utils.h | 12 + configure.ac | 8 - dbus-proxy/flatpak-proxy.c | 251 +++++++++++++++++++++----------------- debian/changelog | 30 ++++ debian/control | 2 debian/tests/control | 11 - lib/flatpak-version-macros.h | 2 tests/Makefile.am.inc | 1 tests/libtest.sh | 5 tests/package_version.txt | 2 tests/test-oci.sh | 5 tests/test-run.sh | 15 ++ tests/test-webserver.sh | 21 +++ tests/testlibrary.c | 16 ++ 21 files changed, 355 insertions(+), 163 deletions(-) diff -Nru --exclude po --exclude Makefile.in --exclude html --exclude configure flatpak-0.8.4/app/flatpak-builtins-add-remote.c flatpak-0.8.5/app/flatpak-builtins-add-remote.c --- flatpak-0.8.4/app/flatpak-builtins-add-remote.c 2017-03-10 09:17:20.000000000 +0000 +++ flatpak-0.8.5/app/flatpak-builtins-add-remote.c 2017-04-03 12:44:34.000000000 +0100 @@ -398,7 +398,7 @@ } if (opt_from || - g_str_has_suffix (location, ".flatpakrepo")) + flatpak_file_arg_has_suffix (location, ".flatpakrepo")) { load_options (location, &gpg_data); if (opt_url == NULL) diff -Nru --exclude po --exclude Makefile.in --exclude html --exclude configure flatpak-0.8.4/app/flatpak-builtins-install.c flatpak-0.8.5/app/flatpak-builtins-install.c --- flatpak-0.8.4/app/flatpak-builtins-install.c 2017-03-10 09:17:20.000000000 +0000 +++ flatpak-0.8.5/app/flatpak-builtins-install.c 2017-04-03 12:46:15.000000000 +0100 @@ -440,9 +440,9 @@ if (!opt_bundle && !opt_from && !opt_oci && argc >= 2) { - if (g_str_has_suffix (argv[1], ".flatpakref")) + if (flatpak_file_arg_has_suffix (argv[1], ".flatpakref")) opt_from = TRUE; - if (g_str_has_suffix (argv[1], ".flatpak")) + if (flatpak_file_arg_has_suffix (argv[1], ".flatpak")) opt_bundle = TRUE; } diff -Nru --exclude po --exclude Makefile.in --exclude html --exclude configure flatpak-0.8.4/app/flatpak-builtins-update.c flatpak-0.8.5/app/flatpak-builtins-update.c --- flatpak-0.8.4/app/flatpak-builtins-update.c 2017-02-10 15:13:02.000000000 +0000 +++ flatpak-0.8.5/app/flatpak-builtins-update.c 2017-04-03 12:29:24.000000000 +0100 @@ -60,7 +60,7 @@ { "app", 0, 0, G_OPTION_ARG_NONE, &opt_app, N_("Look for app with the specified name"), NULL }, { "appstream", 0, 0, G_OPTION_ARG_NONE, &opt_appstream, N_("Update appstream for remote"), NULL }, { "subpath", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &opt_subpaths, N_("Only update this subpath"), N_("PATH") }, - { "assumeyes", 'y', 0, G_OPTION_ARG_NONE, &opt_yes, N_("OAutomatically answer yes for all questions"), NULL }, + { "assumeyes", 'y', 0, G_OPTION_ARG_NONE, &opt_yes, N_("Automatically answer yes for all questions"), NULL }, { NULL } }; diff -Nru --exclude po --exclude Makefile.in --exclude html --exclude configure flatpak-0.8.4/common/flatpak-dir.c flatpak-0.8.5/common/flatpak-dir.c --- flatpak-0.8.4/common/flatpak-dir.c 2017-03-10 09:20:21.000000000 +0000 +++ flatpak-0.8.5/common/flatpak-dir.c 2017-04-03 12:44:28.000000000 +0100 @@ -1709,6 +1709,7 @@ const char **dirs_to_pull, const char *ref_to_fetch, const char *rev_to_fetch, + FlatpakPullFlags flatpak_flags, OstreeRepoPullFlags flags, OstreeAsyncProgress *progress, GCancellable *cancellable, @@ -1716,7 +1717,11 @@ { GVariantBuilder builder; gboolean force_disable_deltas = FALSE; + g_autofree char *remote_and_branch = NULL; + g_autofree char *current_checksum = NULL; g_autoptr(GVariant) options = NULL; + g_autoptr(GVariant) old_commit = NULL; + g_autoptr(GVariant) new_commit = NULL; const char *refs_to_fetch[2]; const char *revs_to_fetch[2]; gboolean res; @@ -1751,9 +1756,33 @@ g_variant_new_variant (g_variant_new_strv ((const char * const *) revs_to_fetch, -1))); options = g_variant_ref_sink (g_variant_builder_end (&builder)); + + remote_and_branch = g_strdup_printf ("%s:%s", remote_name, ref_to_fetch); + if (!ostree_repo_resolve_rev (self, remote_and_branch, TRUE, ¤t_checksum, error)) + return FALSE; + if (current_checksum != NULL && + !ostree_repo_load_commit (self, current_checksum, &old_commit, NULL, error)) + return FALSE; + res = ostree_repo_pull_with_options (self, remote_name, options, progress, cancellable, error); + if (old_commit && + (flatpak_flags & FLATPAK_PULL_FLAGS_ALLOW_DOWNGRADE) == 0) + { + guint64 old_timestamp; + guint64 new_timestamp; + + if (!ostree_repo_load_commit (self, rev_to_fetch, &new_commit, NULL, error)) + return FALSE; + + old_timestamp = ostree_commit_get_timestamp (old_commit); + new_timestamp = ostree_commit_get_timestamp (new_commit); + + if (new_timestamp < old_timestamp) + return flatpak_fail (error, "Update is older then current version"); + } + return res; } @@ -2154,7 +2183,7 @@ if (!repo_pull_one_dir (repo, repository, subdirs_arg ? (const char **)subdirs_arg->pdata : NULL, - ref, rev, flags, + ref, rev, flatpak_flags, flags, progress, cancellable, error)) { @@ -2267,10 +2296,12 @@ g_autoptr(GFile) summary_sig_file = g_file_get_child (path_file, "summary.sig"); g_autofree char *url = g_file_get_uri (path_file); g_autofree char *checksum = NULL; + g_autofree char *current_checksum = NULL; gboolean gpg_verify_summary; gboolean gpg_verify; char *summary_data = NULL; char *summary_sig_data = NULL; + g_autofree char *remote_and_branch = NULL; gsize summary_data_size, summary_sig_data_size; g_autoptr(GBytes) summary_bytes = NULL; g_autoptr(GBytes) summary_sig_bytes = NULL; @@ -2335,7 +2366,13 @@ return FALSE; } - (void) ostree_repo_load_commit (self->repo, checksum, &old_commit, NULL, NULL); + remote_and_branch = g_strdup_printf ("%s:%s", remote_name, ref); + if (!ostree_repo_resolve_rev (self->repo, remote_and_branch, TRUE, ¤t_checksum, error)) + return FALSE; + + if (current_checksum != NULL && + !ostree_repo_load_commit (self->repo, current_checksum, &old_commit, NULL, NULL)) + return FALSE; src_repo = ostree_repo_new (path_file); if (!ostree_repo_open (src_repo, cancellable, error)) @@ -4771,15 +4808,19 @@ /* We're pulling from a remote source, we do the network mirroring pull as a user and hand back the resulting data to the system-helper, that trusts us due to the GPG signatures in the repo */ + FlatpakPullFlags flatpak_flags; child_repo = flatpak_dir_create_system_child_repo (self, &child_repo_lock, error); if (child_repo == NULL) return FALSE; + flatpak_flags = FLATPAK_PULL_FLAGS_DOWNLOAD_EXTRA_DATA | FLATPAK_PULL_FLAGS_SIDELOAD_EXTRA_DATA; + if (checksum_or_latest != NULL) + flatpak_flags |= FLATPAK_PULL_FLAGS_ALLOW_DOWNGRADE; + if (!flatpak_dir_pull (self, remote_name, ref, rev, subpaths, child_repo, - FLATPAK_PULL_FLAGS_DOWNLOAD_EXTRA_DATA | FLATPAK_PULL_FLAGS_SIDELOAD_EXTRA_DATA, - OSTREE_REPO_PULL_FLAGS_MIRROR, + flatpak_flags, OSTREE_REPO_PULL_FLAGS_MIRROR, progress, cancellable, error)) return FALSE; diff -Nru --exclude po --exclude Makefile.in --exclude html --exclude configure flatpak-0.8.4/common/flatpak-dir.h flatpak-0.8.5/common/flatpak-dir.h --- flatpak-0.8.4/common/flatpak-dir.h 2017-03-10 09:17:20.000000000 +0000 +++ flatpak-0.8.5/common/flatpak-dir.h 2017-04-03 12:44:28.000000000 +0100 @@ -98,6 +98,7 @@ FLATPAK_PULL_FLAGS_NONE = 0, FLATPAK_PULL_FLAGS_DOWNLOAD_EXTRA_DATA = 1 << 0, FLATPAK_PULL_FLAGS_SIDELOAD_EXTRA_DATA = 1 << 1, + FLATPAK_PULL_FLAGS_ALLOW_DOWNGRADE = 1 << 2, } FlatpakPullFlags; typedef enum { diff -Nru --exclude po --exclude Makefile.in --exclude html --exclude configure flatpak-0.8.4/common/flatpak-utils.c flatpak-0.8.5/common/flatpak-utils.c --- flatpak-0.8.4/common/flatpak-utils.c 2017-03-10 09:20:18.000000000 +0000 +++ flatpak-0.8.5/common/flatpak-utils.c 2017-04-03 12:45:21.000000000 +0100 @@ -1023,13 +1023,13 @@ GError **error) { gchar **ret = NULL; - g_autoptr(GPtrArray) names = NULL; g_autoptr(GHashTable) hash = NULL; g_autoptr(FlatpakDir) user_dir = NULL; - g_autoptr(GError) my_error = NULL; const char *key; GHashTableIter iter; + g_autoptr(GPtrArray) system_dirs = NULL; + int i; hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); @@ -1037,28 +1037,21 @@ if (!flatpak_dir_collect_unmaintained_refs (user_dir, name_prefix, branch, arch, hash, cancellable, - &my_error)) - { - g_autoptr(GPtrArray) system_dirs = NULL; - int i; + error)) + return NULL; - system_dirs = flatpak_dir_get_system_list (cancellable, error); - if (system_dirs == NULL) - goto out; + system_dirs = flatpak_dir_get_system_list (cancellable, error); + if (system_dirs == NULL) + return NULL; - for (i = 0; i < system_dirs->len; i++) - { - FlatpakDir *system_dir = g_ptr_array_index (system_dirs, i); + for (i = 0; i < system_dirs->len; i++) + { + FlatpakDir *system_dir = g_ptr_array_index (system_dirs, i); - g_clear_error (&my_error); - if (flatpak_dir_collect_unmaintained_refs (system_dir, name_prefix, - branch, arch, hash, cancellable, - &my_error)) - { - /* Reference found in at least one of the system installations */ - break; - } - } + if (!flatpak_dir_collect_unmaintained_refs (system_dir, name_prefix, + branch, arch, hash, cancellable, + error)) + return NULL; } names = g_ptr_array_new (); @@ -1072,10 +1065,6 @@ ret = (char **) g_ptr_array_free (names, FALSE); names = NULL; - if (ret == NULL) - g_propagate_error (error, g_steal_pointer (&my_error)); - -out: return ret; } @@ -1814,6 +1803,16 @@ spawn_data_exit (data); } +/* This is useful, because it handles escaped characters in uris, and ? arguments at the end of the uri */ +gboolean +flatpak_file_arg_has_suffix (const char *arg, const char *suffix) +{ + g_autoptr(GFile) file = g_file_new_for_commandline_arg (arg); + g_autofree char *basename = g_file_get_basename (file); + + return g_str_has_suffix (basename, suffix); +} + gboolean flatpak_spawn (GFile *dir, char **output, diff -Nru --exclude po --exclude Makefile.in --exclude html --exclude configure flatpak-0.8.4/common/flatpak-utils.h flatpak-0.8.5/common/flatpak-utils.h --- flatpak-0.8.4/common/flatpak-utils.h 2017-03-10 09:17:20.000000000 +0000 +++ flatpak-0.8.5/common/flatpak-utils.h 2017-04-03 12:45:09.000000000 +0100 @@ -343,6 +343,8 @@ const char *arch, const char *branch); +gboolean flatpak_file_arg_has_suffix (const char *arg, const char *suffix); + gboolean flatpak_spawn (GFile *dir, char **output, GError **error, @@ -452,11 +454,21 @@ #define AUTOLOCK(name) G_GNUC_UNUSED __attribute__((cleanup (flatpak_auto_unlock_helper))) GMutex * G_PASTE (auto_unlock, __LINE__) = flatpak_auto_lock_helper (&G_LOCK_NAME (name)) +/* OSTREE_CHECK_VERSION was added immediately after the 2017.3 release */ +#ifndef OSTREE_CHECK_VERSION +#define OSTREE_CHECK_VERSION(year, minor) (0) +#endif +/* Cleanups are always exported in 2017.4, and some git releases between 2017.3 and 2017.4. + We actually check against 2017.3 so that we work on the git releases *after* 2017.3 + which is safe, because the real OSTREE_CHECK_VERSION macro was added after 2017.3 + too. */ +#if !OSTREE_CHECK_VERSION(2017, 3) G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepo, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeMutableTree, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeAsyncProgress, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeGpgVerifyResult, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepoCommitModifier, ostree_repo_commit_modifier_unref) +#endif #ifndef SOUP_AUTOCLEANUPS_H G_DEFINE_AUTOPTR_CLEANUP_FUNC (SoupSession, g_object_unref) diff -Nru --exclude po --exclude Makefile.in --exclude html --exclude configure flatpak-0.8.4/configure.ac flatpak-0.8.5/configure.ac --- flatpak-0.8.4/configure.ac 2017-03-10 09:43:27.000000000 +0000 +++ flatpak-0.8.5/configure.ac 2017-04-03 13:07:27.000000000 +0100 @@ -15,8 +15,8 @@ m4_define([flatpak_major_version], [0]) m4_define([flatpak_minor_version], [8]) -m4_define([flatpak_micro_version], [4]) -m4_define([flatpak_interface_age], [4]) +m4_define([flatpak_micro_version], [5]) +m4_define([flatpak_interface_age], [5]) m4_define([flatpak_binary_age], [m4_eval(10000 * flatpak_major_version + 100 * flatpak_minor_version + flatpak_micro_version)]) m4_define([flatpak_version], @@ -28,7 +28,7 @@ [flatpak], [http://flatpak.org/]) -GLIB_REQS=2.40 +GLIB_REQS=2.44 SYSTEM_BWRAP_REQS=0.1.5 OSTREE_REQS=2016.14 @@ -44,7 +44,7 @@ AC_CONFIG_SRCDIR([common/flatpak-dir.c]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_MACRO_DIR([m4]) -AM_INIT_AUTOMAKE([1.11 no-define no-dist-gzip dist-xz tar-ustar foreign subdir-objects]) +AM_INIT_AUTOMAKE([1.13.4 no-define no-dist-gzip dist-xz tar-ustar foreign subdir-objects]) AC_PROG_SED AM_GNU_GETTEXT([external]) diff -Nru --exclude po --exclude Makefile.in --exclude html --exclude configure flatpak-0.8.4/dbus-proxy/flatpak-proxy.c flatpak-0.8.5/dbus-proxy/flatpak-proxy.c --- flatpak-0.8.4/dbus-proxy/flatpak-proxy.c 2016-10-28 09:41:14.000000000 +0100 +++ flatpak-0.8.5/dbus-proxy/flatpak-proxy.c 2017-04-03 12:44:16.000000000 +0100 @@ -193,6 +193,7 @@ { gsize size; gsize pos; + int refcount; gboolean send_credentials; GList *control_messages; @@ -202,6 +203,7 @@ typedef struct { + Buffer *buffer; gboolean big_endian; guchar type; guchar flags; @@ -219,6 +221,9 @@ guint32 unix_fds; } Header; +static void header_free (Header *header); +G_DEFINE_AUTOPTR_CLEANUP_FUNC (Header, header_free) + typedef struct { gboolean got_first_byte; /* always true on bus side */ @@ -313,19 +318,35 @@ static void stop_reading (ProxySide *side); static void -buffer_free (Buffer *buffer) +buffer_unref (Buffer *buffer) { - g_list_free_full (buffer->control_messages, g_object_unref); - g_free (buffer); + g_assert (buffer->refcount > 0); + buffer->refcount--; + + if (buffer->refcount == 0) + { + g_list_free_full (buffer->control_messages, g_object_unref); + g_free (buffer); + } } +static Buffer * +buffer_ref (Buffer *buffer) +{ + g_assert (buffer->refcount > 0); + buffer->refcount++; + return buffer; +} + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (Buffer, buffer_unref) + static void free_side (ProxySide *side) { g_clear_object (&side->connection); g_clear_pointer (&side->extra_input_data, g_bytes_unref); - g_list_free_full (side->buffers, (GDestroyNotify) buffer_free); + g_list_free_full (side->buffers, (GDestroyNotify) buffer_unref); g_list_free_full (side->control_messages, (GDestroyNotify) g_object_unref); if (side->in_source) @@ -538,6 +559,7 @@ buffer->control_messages = NULL; buffer->size = size; + buffer->refcount = 1; if (old) { @@ -763,7 +785,7 @@ if (buffer->pos == buffer->size) { side->buffers = g_list_delete_link (side->buffers, side->buffers); - buffer_free (buffer); + buffer_unref (buffer); } } else @@ -907,29 +929,38 @@ return str; } -static gboolean -parse_header (Buffer *buffer, Header *header, guint32 serial_offset, guint32 reply_serial_offset, guint32 hello_serial) +static void +header_free (Header *header) +{ + if (header->buffer) + buffer_unref (header->buffer); + g_free (header); +} + +static Header * +parse_header (Buffer *buffer, guint32 serial_offset, guint32 reply_serial_offset, guint32 hello_serial) { guint32 array_len, header_len; guint32 offset, end_offset; guint8 header_type; guint32 reply_serial_pos = 0; const char *signature; + g_autoptr(Header) header = g_new0 (Header, 1); - memset (header, 0, sizeof (Header)); + header->buffer = buffer_ref (buffer); if (buffer->size < 16) - return FALSE; + return NULL; if (buffer->data[3] != 1) /* Protocol version */ - return FALSE; + return NULL; if (buffer->data[0] == 'B') header->big_endian = TRUE; else if (buffer->data[0] == 'l') header->big_endian = FALSE; else - return FALSE; + return NULL; header->type = buffer->data[1]; header->flags = buffer->data[2]; @@ -938,14 +969,14 @@ header->serial = read_uint32 (header, &buffer->data[8]); if (header->serial == 0) - return FALSE; + return NULL; array_len = read_uint32 (header, &buffer->data[12]); header_len = align_by_8 (12 + 4 + array_len); g_assert (buffer->size >= header_len); /* We should have verified this when reading in the message */ if (header_len > buffer->size) - return FALSE; + return NULL; offset = 12 + 4; end_offset = offset + array_len; @@ -954,56 +985,56 @@ { offset = align_by_8 (offset); /* Structs must be 8 byte aligned */ if (offset >= end_offset) - return FALSE; + return NULL; header_type = buffer->data[offset++]; if (offset >= end_offset) - return FALSE; + return NULL; signature = get_signature (buffer, &offset, end_offset); if (signature == NULL) - return FALSE; + return NULL; switch (header_type) { case G_DBUS_MESSAGE_HEADER_FIELD_INVALID: - return FALSE; + return NULL; case G_DBUS_MESSAGE_HEADER_FIELD_PATH: if (strcmp (signature, "o") != 0) - return FALSE; + return NULL; header->path = get_string (buffer, header, &offset, end_offset); if (header->path == NULL) - return FALSE; + return NULL; break; case G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE: if (strcmp (signature, "s") != 0) - return FALSE; + return NULL; header->interface = get_string (buffer, header, &offset, end_offset); if (header->interface == NULL) - return FALSE; + return NULL; break; case G_DBUS_MESSAGE_HEADER_FIELD_MEMBER: if (strcmp (signature, "s") != 0) - return FALSE; + return NULL; header->member = get_string (buffer, header, &offset, end_offset); if (header->member == NULL) - return FALSE; + return NULL; break; case G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME: if (strcmp (signature, "s") != 0) - return FALSE; + return NULL; header->error_name = get_string (buffer, header, &offset, end_offset); if (header->error_name == NULL) - return FALSE; + return NULL; break; case G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL: if (offset + 4 > end_offset) - return FALSE; + return NULL; header->has_reply_serial = TRUE; reply_serial_pos = offset; @@ -1013,31 +1044,31 @@ case G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION: if (strcmp (signature, "s") != 0) - return FALSE; + return NULL; header->destination = get_string (buffer, header, &offset, end_offset); if (header->destination == NULL) - return FALSE; + return NULL; break; case G_DBUS_MESSAGE_HEADER_FIELD_SENDER: if (strcmp (signature, "s") != 0) - return FALSE; + return NULL; header->sender = get_string (buffer, header, &offset, end_offset); if (header->sender == NULL) - return FALSE; + return NULL; break; case G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE: if (strcmp (signature, "g") != 0) - return FALSE; + return NULL; header->signature = get_signature (buffer, &offset, end_offset); if (header->signature == NULL) - return FALSE; + return NULL; break; case G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS: if (offset + 4 > end_offset) - return FALSE; + return NULL; header->unix_fds = read_uint32 (header, &buffer->data[offset]); offset += 4; @@ -1045,7 +1076,7 @@ default: /* Unknown header field, for safety, fail parse */ - return FALSE; + return NULL; } } @@ -1053,32 +1084,32 @@ { case G_DBUS_MESSAGE_TYPE_METHOD_CALL: if (header->path == NULL || header->member == NULL) - return FALSE; + return NULL; break; case G_DBUS_MESSAGE_TYPE_METHOD_RETURN: if (!header->has_reply_serial) - return FALSE; + return NULL; break; case G_DBUS_MESSAGE_TYPE_ERROR: if (header->error_name == NULL || !header->has_reply_serial) - return FALSE; + return NULL; break; case G_DBUS_MESSAGE_TYPE_SIGNAL: if (header->path == NULL || header->interface == NULL || header->member == NULL) - return FALSE; + return NULL; if (strcmp (header->path, "/org/freedesktop/DBus/Local") == 0 || strcmp (header->interface, "org.freedesktop.DBus.Local") == 0) - return FALSE; + return NULL; break; default: /* Unknown message type, for safety, fail parse */ - return FALSE; + return NULL; } if (serial_offset > 0) @@ -1092,7 +1123,7 @@ header->reply_serial > hello_serial + reply_serial_offset) write_uint32 (header, &buffer->data[reply_serial_pos], header->reply_serial - reply_serial_offset); - return TRUE; + return g_steal_pointer (&header); } static void @@ -1456,7 +1487,8 @@ get_arg0_string (Buffer *buffer) { GDBusMessage *message = g_dbus_message_new_from_blob (buffer->data, buffer->size, 0, NULL); - GVariant *body, *arg0; + GVariant *body; + g_autoptr(GVariant) arg0 = NULL; char *name = NULL; if (message != NULL && @@ -1644,7 +1676,7 @@ { g_warning ("Not enough fds for message"); side_closed (side); - buffer_free (buffer); + buffer_unref (buffer); return FALSE; } } @@ -1794,46 +1826,47 @@ if (client->authenticated && client->proxy->filter) { - Header header; + g_autoptr(Header) header = NULL;; BusHandler handler; /* Filter and rewrite outgoing messages as needed */ - if (!parse_header (buffer, &header, client->serial_offset, 0, 0)) + header = parse_header (buffer, client->serial_offset, 0, 0); + if (header == NULL) { g_warning ("Invalid message header format"); side_closed (side); - buffer_free (buffer); + buffer_unref (buffer); return; } - if (!update_socket_messages (side, buffer, &header)) + if (!update_socket_messages (side, buffer, header)) return; /* Make sure the client is not playing games with the serials, as that could confuse us. */ - if (header.serial <= client->last_serial) + if (header->serial <= client->last_serial) { g_warning ("Invalid client serial"); side_closed (side); - buffer_free (buffer); + buffer_unref (buffer); return; } - client->last_serial = header.serial; + client->last_serial = header->serial; if (client->proxy->log_messages) - print_outgoing_header (&header); + print_outgoing_header (header); /* Keep track of the initial Hello request so that we can read the reply which has our assigned unique id */ - if (is_dbus_method_call (&header) && - g_strcmp0 (header.member, "Hello") == 0) + if (is_dbus_method_call (header) && + g_strcmp0 (header->member, "Hello") == 0) { expecting_reply = EXPECTED_REPLY_HELLO; - client->hello_serial = header.serial; + client->hello_serial = header->serial; } - handler = get_dbus_method_handler (client, &header); + handler = get_dbus_method_handler (client, header); switch (handler) { @@ -1841,12 +1874,12 @@ case HANDLE_FILTER_GET_OWNER_REPLY: if (!validate_arg0_name (client, buffer, FLATPAK_POLICY_SEE, NULL)) { - g_clear_pointer (&buffer, buffer_free); + g_clear_pointer (&buffer, buffer_unref); if (handler == HANDLE_FILTER_GET_OWNER_REPLY) - buffer = get_error_for_roundtrip (client, &header, + buffer = get_error_for_roundtrip (client, header, "org.freedesktop.DBus.Error.NameHasNoOwner"); else - buffer = get_bool_reply_for_roundtrip (client, &header, FALSE); + buffer = get_bool_reply_for_roundtrip (client, header, FALSE); expecting_reply = EXPECTED_REPLY_REWRITE; break; @@ -1874,7 +1907,7 @@ case HANDLE_PASS: handle_pass: - if (client_message_generates_reply (&header)) + if (client_message_generates_reply (header)) { if (expecting_reply == EXPECTED_REPLY_NONE) expecting_reply = EXPECTED_REPLY_NORMAL; @@ -1884,22 +1917,22 @@ case HANDLE_HIDE: handle_hide: - g_clear_pointer (&buffer, buffer_free); + g_clear_pointer (&buffer, buffer_unref); - if (client_message_generates_reply (&header)) + if (client_message_generates_reply (header)) { const char *error; if (client->proxy->log_messages) g_print ("*HIDDEN* (ping)\n"); - if ((header.destination != NULL && header.destination[0] == ':') || - (header.flags & G_DBUS_MESSAGE_FLAGS_NO_AUTO_START) != 0) + if ((header->destination != NULL && header->destination[0] == ':') || + (header->flags & G_DBUS_MESSAGE_FLAGS_NO_AUTO_START) != 0) error = "org.freedesktop.DBus.Error.NameHasNoOwner"; else error = "org.freedesktop.DBus.Error.ServiceUnknown"; - buffer = get_error_for_roundtrip (client, &header, error); + buffer = get_error_for_roundtrip (client, header, error); expecting_reply = EXPECTED_REPLY_REWRITE; } else @@ -1912,14 +1945,14 @@ default: case HANDLE_DENY: handle_deny: - g_clear_pointer (&buffer, buffer_free); + g_clear_pointer (&buffer, buffer_unref); - if (client_message_generates_reply (&header)) + if (client_message_generates_reply (header)) { if (client->proxy->log_messages) g_print ("*DENIED* (ping)\n"); - buffer = get_error_for_roundtrip (client, &header, + buffer = get_error_for_roundtrip (client, header, "org.freedesktop.DBus.Error.AccessDenied"); expecting_reply = EXPECTED_REPLY_REWRITE; } @@ -1932,7 +1965,7 @@ } if (buffer != NULL && expecting_reply != EXPECTED_REPLY_NONE) - queue_expected_reply (side, header.serial, expecting_reply); + queue_expected_reply (side, header->serial, expecting_reply); } if (buffer) @@ -1947,37 +1980,38 @@ { if (client->authenticated && client->proxy->filter) { - Header header; + g_autoptr(Header) header = NULL;; GDBusMessage *rewritten; FlatpakPolicy policy; ExpectedReplyType expected_reply; /* Filter and rewrite incoming messages as needed */ - if (!parse_header (buffer, &header, 0, client->serial_offset, client->hello_serial)) + header = parse_header (buffer, 0, client->serial_offset, client->hello_serial); + if (header == NULL) { g_warning ("Invalid message header format"); - buffer_free (buffer); + buffer_unref (buffer); side_closed (side); return; } - if (!update_socket_messages (side, buffer, &header)) + if (!update_socket_messages (side, buffer, header)) return; if (client->proxy->log_messages) - print_incoming_header (&header); + print_incoming_header (header); - if (header.has_reply_serial) + if (header->has_reply_serial) { - expected_reply = steal_expected_reply (get_other_side (side), header.reply_serial); + expected_reply = steal_expected_reply (get_other_side (side), header->reply_serial); /* We only allow replies we expect */ if (expected_reply == EXPECTED_REPLY_NONE) { if (client->proxy->log_messages) g_print ("*Unexpected reply*\n"); - buffer_free (buffer); + buffer_unref (buffer); return; } @@ -1986,9 +2020,9 @@ case EXPECTED_REPLY_HELLO: /* When we get the initial reply to Hello, allow all further communications to our own unique id. */ - if (header.type == G_DBUS_MESSAGE_TYPE_METHOD_RETURN) + if (header->type == G_DBUS_MESSAGE_TYPE_METHOD_RETURN) { - char *my_id = get_arg0_string (buffer); + g_autofree char *my_id = get_arg0_string (buffer); flatpak_proxy_client_update_unique_id_policy (client, my_id, FLATPAK_POLICY_TALK); break; } @@ -1997,17 +2031,17 @@ /* Replace a roundtrip ping with the rewritten message */ rewritten = g_hash_table_lookup (client->rewrite_reply, - GINT_TO_POINTER (header.reply_serial)); + GINT_TO_POINTER (header->reply_serial)); if (client->proxy->log_messages) g_print ("*REWRITTEN*\n"); - g_dbus_message_set_serial (rewritten, header.serial); - g_clear_pointer (&buffer, buffer_free); + g_dbus_message_set_serial (rewritten, header->serial); + g_clear_pointer (&buffer, buffer_unref); buffer = message_to_buffer (rewritten); g_hash_table_remove (client->rewrite_reply, - GINT_TO_POINTER (header.reply_serial)); + GINT_TO_POINTER (header->reply_serial)); break; case EXPECTED_REPLY_FAKE_LIST_NAMES: @@ -2015,12 +2049,12 @@ request, request ownership of any name matching a wildcard policy */ - queue_wildcard_initial_name_ops (client, &header, buffer); + queue_wildcard_initial_name_ops (client, header, buffer); /* Don't forward fake replies to the app */ if (client->proxy->log_messages) g_print ("*SKIPPED*\n"); - g_clear_pointer (&buffer, buffer_free); + g_clear_pointer (&buffer, buffer_unref); /* Start reading the clients requests now that we are done with the names */ start_reading (&client->client_side); @@ -2031,39 +2065,38 @@ request, update the policy for this unique name based on the policy */ { - char *requested_name = g_hash_table_lookup (client->get_owner_reply, GINT_TO_POINTER (header.reply_serial)); + char *requested_name = g_hash_table_lookup (client->get_owner_reply, GINT_TO_POINTER (header->reply_serial)); - if (header.type == G_DBUS_MESSAGE_TYPE_METHOD_RETURN) + if (header->type == G_DBUS_MESSAGE_TYPE_METHOD_RETURN) { - char *owner = get_arg0_string (buffer); + g_autofree char *owner = get_arg0_string (buffer); flatpak_proxy_client_update_unique_id_policy_from_name (client, owner, requested_name); - g_free (owner); } - g_hash_table_remove (client->get_owner_reply, GINT_TO_POINTER (header.reply_serial)); + g_hash_table_remove (client->get_owner_reply, GINT_TO_POINTER (header->reply_serial)); /* Don't forward fake replies to the app */ if (client->proxy->log_messages) g_print ("*SKIPPED*\n"); - g_clear_pointer (&buffer, buffer_free); + g_clear_pointer (&buffer, buffer_unref); break; } case EXPECTED_REPLY_FILTER: if (client->proxy->log_messages) g_print ("*SKIPPED*\n"); - g_clear_pointer (&buffer, buffer_free); + g_clear_pointer (&buffer, buffer_unref); break; case EXPECTED_REPLY_LIST_NAMES: /* This is a reply from the bus to a ListNames request, filter it according to the policy */ - if (header.type == G_DBUS_MESSAGE_TYPE_METHOD_RETURN) + if (header->type == G_DBUS_MESSAGE_TYPE_METHOD_RETURN) { Buffer *filtered_buffer; filtered_buffer = filter_names_list (client, buffer); - g_clear_pointer (&buffer, buffer_free); + g_clear_pointer (&buffer, buffer_unref); buffer = filtered_buffer; } @@ -2080,41 +2113,41 @@ { /* Don't allow reply types with no reply_serial */ - if (header.type == G_DBUS_MESSAGE_TYPE_METHOD_RETURN || - header.type == G_DBUS_MESSAGE_TYPE_ERROR) + if (header->type == G_DBUS_MESSAGE_TYPE_METHOD_RETURN || + header->type == G_DBUS_MESSAGE_TYPE_ERROR) { if (client->proxy->log_messages) g_print ("*Invalid reply*\n"); - g_clear_pointer (&buffer, buffer_free); + g_clear_pointer (&buffer, buffer_unref); } /* We filter all NameOwnerChanged signal according to the policy */ - if (message_is_name_owner_changed (client, &header)) + if (message_is_name_owner_changed (client, header)) { if (should_filter_name_owner_changed (client, buffer)) - g_clear_pointer (&buffer, buffer_free); + g_clear_pointer (&buffer, buffer_unref); } } /* All incoming broadcast signals are filtered according to policy */ - if (header.type == G_DBUS_MESSAGE_TYPE_SIGNAL && header.destination == NULL) + if (header->type == G_DBUS_MESSAGE_TYPE_SIGNAL && header->destination == NULL) { - policy = flatpak_proxy_client_get_policy (client, header.sender); + policy = flatpak_proxy_client_get_policy (client, header->sender); if (policy < FLATPAK_POLICY_TALK) { if (client->proxy->log_messages) g_print ("*FILTERED IN*\n"); - g_clear_pointer (&buffer, buffer_free); + g_clear_pointer (&buffer, buffer_unref); } } /* We received and forwarded a message from a trusted peer. Make the policy for this unique id SEE so that the client can track its lifetime. */ - if (buffer && header.sender && header.sender[0] == ':') - flatpak_proxy_client_update_unique_id_policy (client, header.sender, FLATPAK_POLICY_SEE); + if (buffer && header->sender && header->sender[0] == ':') + flatpak_proxy_client_update_unique_id_policy (client, header->sender, FLATPAK_POLICY_SEE); - if (buffer && client_message_generates_reply (&header)) - queue_expected_reply (side, header.serial, EXPECTED_REPLY_NORMAL); + if (buffer && client_message_generates_reply (header)) + queue_expected_reply (side, header->serial, EXPECTED_REPLY_NORMAL); } if (buffer) @@ -2200,7 +2233,11 @@ buffer = side->current_read_buffer; if (!buffer_read (side, buffer, socket)) - break; + { + if (buffer != side->current_read_buffer) + buffer_unref (buffer); + break; + } if (!client->authenticated) { @@ -2240,7 +2277,7 @@ } else { - buffer_free (buffer); + buffer_unref (buffer); } } else if (buffer->pos == buffer->size) diff -Nru --exclude po --exclude Makefile.in --exclude html --exclude configure flatpak-0.8.4/debian/changelog flatpak-0.8.5/debian/changelog --- flatpak-0.8.4/debian/changelog 2017-03-15 18:43:51.000000000 +0000 +++ flatpak-0.8.5/debian/changelog 2017-04-03 16:35:44.000000000 +0100 @@ -1,3 +1,33 @@ +flatpak (0.8.5-1) unstable; urgency=medium + + * New upstream bugfix release + * Upstream security fixes: + - dbus-proxy: Fix a use-after-free (no specific exploit is known) + and several memory leaks + - system-helper: Correct the check that was meant to prevent + unprivileged users from downgrading system-wide-installed apps + - Do not allow downgrading apps to validly-signed older versions + unless a specific older version is requested, so that a + man-in-the-middle cannot cause a downgrade to an older app + version with a vulnerability + * Other upstream fixes: + - Increase GLib build-dependency to 2.44 (in practice this was + already required, there is a patch in jessie-backports to + relax this) + - Collect system extension references from all system directories, + not just the first that exists (upstream issue 654) + - Stop using ostree trivial-httpd, which is not available in + post-stretch ostree (upstream issues 658, 723) + - Be build-time compatible with post-stretch ostree (upstream + issue 756) + - Strip ?query suffix before detecting whether a URI points to a + .flatpakref or .flatpakrepo file (upstream issue 659) + - Fix a typo in help output + * d/tests/control: most tests now require python, for the + ostree-trivial-httpd replacement + + -- Simon McVittie <s...@debian.org> Mon, 03 Apr 2017 16:35:44 +0100 + flatpak (0.8.4-3) unstable; urgency=medium * Mark the one remaining patch as applied in 0.9.1 diff -Nru --exclude po --exclude Makefile.in --exclude html --exclude configure flatpak-0.8.4/debian/control flatpak-0.8.5/debian/control --- flatpak-0.8.4/debian/control 2017-03-15 18:43:51.000000000 +0000 +++ flatpak-0.8.5/debian/control 2017-04-03 16:35:44.000000000 +0100 @@ -30,7 +30,7 @@ libelf-dev, libfuse-dev, libgirepository1.0-dev, - libglib2.0-dev, + libglib2.0-dev (>= 2.44), libjson-glib-dev, libostree-dev (>= 2016.15), libpolkit-gobject-1-dev, diff -Nru --exclude po --exclude Makefile.in --exclude html --exclude configure flatpak-0.8.4/debian/tests/control flatpak-0.8.5/debian/tests/control --- flatpak-0.8.4/debian/tests/control 2017-03-15 18:43:51.000000000 +0000 +++ flatpak-0.8.5/debian/tests/control 2017-04-03 16:35:44.000000000 +0100 @@ -3,7 +3,7 @@ build-essential, libflatpak-dev, -Tests: builder +Tests: builder builder-python Restrictions: isolation-machine Depends: flatpak-builder, @@ -11,14 +11,6 @@ git, gnome-desktop-testing, make, - -Tests: builder-python -Restrictions: isolation-machine -Depends: - flatpak-builder, - flatpak-tests, - gnome-desktop-testing, - make, python, Tests: gnome-desktop-testing @@ -26,3 +18,4 @@ Depends: flatpak-tests, gnome-desktop-testing, + python, diff -Nru --exclude po --exclude Makefile.in --exclude html --exclude configure flatpak-0.8.4/lib/flatpak-version-macros.h flatpak-0.8.5/lib/flatpak-version-macros.h --- flatpak-0.8.4/lib/flatpak-version-macros.h 2017-03-10 09:43:54.000000000 +0000 +++ flatpak-0.8.5/lib/flatpak-version-macros.h 2017-04-03 13:07:52.000000000 +0100 @@ -27,7 +27,7 @@ #define FLATPAK_MAJOR_VERSION (0) #define FLATPAK_MINOR_VERSION (8) -#define FLATPAK_MICRO_VERSION (4) +#define FLATPAK_MICRO_VERSION (5) #define FLATPAK_CHECK_VERSION(major,minor,micro) \ (FLATPAK_MAJOR_VERSION > (major) || \ diff -Nru --exclude po --exclude Makefile.in --exclude html --exclude configure flatpak-0.8.4/NEWS flatpak-0.8.5/NEWS --- flatpak-0.8.4/NEWS 2017-03-10 09:35:30.000000000 +0000 +++ flatpak-0.8.5/NEWS 2017-04-03 13:06:41.000000000 +0100 @@ -1,3 +1,33 @@ +Major changes in 0.8.5 +====================== + +This is a security update for the stable branch, and all users are +recommended to update. + + * Fixed a use-after-free and some leaks in the dbus-proxy. This + is not currently believed to be exploitable, but the proxy is a + security boundary, so we still recommend to update. + * Regular updates now never allow updates to an older version + than what is currently installed (unless you explicitly specify + an old commit id). This closes a hole where a MITM attacker can + force clients to downgrade to an earlier (gpg-signed) version of + the application. + * The automatic detection of --from in flatpak install now detects + flatpakref extensions even in URIs that end in a query string such as + https://git.gnome.org/browse/gnome-apps-nightly/plain/gedit.flatpakref?h=stable + * The detection of "unmaintained" system extensions was broken, and + in some cases these extensions were not found. This now always + works. + * Flatpak now builds with latest OSTree. This required some fixing for + multiple definitions of the g_auto* macros as OSTree now exports + those. + * We no longer rely on ostree trivial-httpd for the tests, because + this is optional in later versions of ostree. Instead we use + they python SimpleHTTPServer. + * The minimum glib version has been corrected to 2.44. + * The minumum automake version has been increased to 1.13.4 + because some older version didn't work. + Major changes in 0.8.4 ====================== diff -Nru --exclude po --exclude Makefile.in --exclude html --exclude configure flatpak-0.8.4/tests/libtest.sh flatpak-0.8.5/tests/libtest.sh --- flatpak-0.8.4/tests/libtest.sh 2017-02-16 08:48:14.000000000 +0000 +++ flatpak-0.8.5/tests/libtest.sh 2017-04-03 12:31:25.000000000 +0100 @@ -180,8 +180,9 @@ GPGARGS="$FL_GPGARGS" . $(dirname $0)/make-test-runtime.sh org.test.Platform bash ls cat echo readlink > /dev/null GPGARGS="$FL_GPGARGS" . $(dirname $0)/make-test-app.sh > /dev/null update_repo - ostree trivial-httpd --autoexit --daemonize -p httpd-port repos + $(dirname $0)/test-webserver.sh repos port=$(cat httpd-port) + FLATPAK_HTTP_PID=$(cat httpd-pid) flatpak remote-add ${U} --gpg-import=${FL_GPG_HOMEDIR}/pubring.gpg test-repo "http://127.0.0.1:${port}/test" } @@ -266,7 +267,7 @@ fi cleanup () { - /bin/kill $DBUS_SESSION_BUS_PID + /bin/kill $DBUS_SESSION_BUS_PID ${FLATPAK_HTTP_PID:-} gpg-connect-agent --homedir "${FL_GPG_HOMEDIR}" killagent /bye || true fusermount -u $XDG_RUNTIME_DIR/doc || : rm -rf $TEST_DATA_DIR diff -Nru --exclude po --exclude Makefile.in --exclude html --exclude configure flatpak-0.8.4/tests/Makefile.am.inc flatpak-0.8.5/tests/Makefile.am.inc --- flatpak-0.8.4/tests/Makefile.am.inc 2017-02-10 15:13:02.000000000 +0000 +++ flatpak-0.8.5/tests/Makefile.am.inc 2017-04-03 12:31:25.000000000 +0100 @@ -80,6 +80,7 @@ tests/make-test-runtime.sh \ tests/make-test-bundles.sh \ tests/testpython.py \ + tests/test-webserver.sh \ $(NULL) dist_installed_test_data = \ diff -Nru --exclude po --exclude Makefile.in --exclude html --exclude configure flatpak-0.8.4/tests/package_version.txt flatpak-0.8.5/tests/package_version.txt --- flatpak-0.8.4/tests/package_version.txt 2017-03-10 09:43:54.000000000 +0000 +++ flatpak-0.8.5/tests/package_version.txt 2017-04-03 13:08:08.000000000 +0100 @@ -1 +1 @@ -0.8.4 +0.8.5 diff -Nru --exclude po --exclude Makefile.in --exclude html --exclude configure flatpak-0.8.4/tests/testlibrary.c flatpak-0.8.5/tests/testlibrary.c --- flatpak-0.8.4/tests/testlibrary.c 2017-02-21 17:54:09.000000000 +0000 +++ flatpak-0.8.5/tests/testlibrary.c 2017-04-03 12:31:25.000000000 +0100 @@ -12,6 +12,7 @@ static char *gpg_homedir; static char *gpg_args; static char *repo_url; +int httpd_pid = -1; static const char *gpg_id = "7B0961FD"; const char *repo_name = "test-repo"; @@ -605,7 +606,8 @@ { int status; g_autoptr(GError) error = NULL; - char *argv[] = { "ostree", "trivial-httpd", "--autoexit", "--daemonize", "-p", "http-port", "repos", NULL }; + g_autofree char *path = g_test_build_filename (G_TEST_DIST, "test-webserver.sh", NULL); + char *argv[] = {path , "repos", NULL }; GSpawnFlags flags = G_SPAWN_SEARCH_PATH; if (g_test_verbose ()) @@ -629,11 +631,18 @@ char *argv[] = { "flatpak", "remote-add", "--user", "--gpg-import=", "name", "url", NULL }; g_autofree char *gpgimport = NULL; g_autofree char *port = NULL; + g_autofree char *pid = NULL; GSpawnFlags flags = G_SPAWN_SEARCH_PATH; launch_httpd (); - g_file_get_contents ("http-port", &port, NULL, &error); + g_file_get_contents ("httpd-pid", &pid, NULL, &error); + g_assert_no_error (error); + + httpd_pid = atoi (pid); + g_assert_cmpint (httpd_pid, !=, 0); + + g_file_get_contents ("httpd-port", &port, NULL, &error); g_assert_no_error (error); if (port[strlen (port) - 1] == '\n') @@ -824,6 +833,9 @@ flags |= G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL; } + if (httpd_pid != -1) + kill (httpd_pid, SIGKILL); + /* mostly ignore failure here */ if (!g_spawn_sync (NULL, (char **)argv, NULL, flags, NULL, NULL, NULL, NULL, &status, &error) || !g_spawn_check_exit_status (status, &error)) diff -Nru --exclude po --exclude Makefile.in --exclude html --exclude configure flatpak-0.8.4/tests/test-oci.sh flatpak-0.8.5/tests/test-oci.sh --- flatpak-0.8.4/tests/test-oci.sh 2017-02-10 15:13:02.000000000 +0000 +++ flatpak-0.8.5/tests/test-oci.sh 2017-04-03 12:43:56.000000000 +0100 @@ -77,8 +77,9 @@ make_updated_app HTTP ${FLATPAK} build-bundle --oci repos/test oci-dir org.test.Hello -ostree trivial-httpd --autoexit --daemonize -p oci-port `pwd`/oci-dir -ociport=$(cat oci-port) +$(dirname $0)/test-webserver.sh `pwd`/oci-dir +ociport=$(cat httpd-port) +FLATPAK_HTTP_PID="${FLATPAK_HTTP_PID} $(cat httpd-pid)" ${FLATPAK} install -v ${U} --oci http://127.0.0.1:${ociport} latest diff -Nru --exclude po --exclude Makefile.in --exclude html --exclude configure flatpak-0.8.4/tests/test-run.sh flatpak-0.8.5/tests/test-run.sh --- flatpak-0.8.4/tests/test-run.sh 2017-02-10 15:13:02.000000000 +0000 +++ flatpak-0.8.5/tests/test-run.sh 2017-04-03 12:44:28.000000000 +0100 @@ -24,7 +24,7 @@ skip_without_bwrap skip_without_user_xattrs -echo "1..9" +echo "1..10" setup_repo install_repo @@ -206,6 +206,19 @@ echo "ok update" +ostree --repo=repos/test reset app/org.test.Hello/$ARCH/master "$OLD_COMMIT" +update_repo + +if ${FLATPAK} ${U} update org.test.Hello; then + assert_not_reached "Should not be able to update to older commit" +fi + +NEW_NEW_COMMIT=`${FLATPAK} ${U} info --show-commit org.test.Hello` + +assert_streq "$NEW_COMMIT" "$NEW_NEW_COMMIT" + +echo "ok backwards update" + DIR=`mktemp -d` ${FLATPAK} build-init ${DIR} org.test.Split org.test.Platform org.test.Platform diff -Nru --exclude po --exclude Makefile.in --exclude html --exclude configure flatpak-0.8.4/tests/test-webserver.sh flatpak-0.8.5/tests/test-webserver.sh --- flatpak-0.8.4/tests/test-webserver.sh 1970-01-01 01:00:00.000000000 +0100 +++ flatpak-0.8.5/tests/test-webserver.sh 2017-04-03 12:34:49.000000000 +0100 @@ -0,0 +1,21 @@ +#!/bin/bash + +set -euo pipefail + +dir=$1 +test_tmpdir=$(pwd) + +cd ${dir} +env PYTHONUNBUFFERED=1 setsid python -m SimpleHTTPServer 0 >${test_tmpdir}/httpd-output & +child_pid=$! + +for x in $(seq 50); do + sed -e 's,Serving HTTP on 0.0.0.0 port \([0-9]*\) \.\.\.,\1,' < ${test_tmpdir}/httpd-output > ${test_tmpdir}/httpd-port + if ! cmp ${test_tmpdir}/httpd-output ${test_tmpdir}/httpd-port 1>/dev/null; then + break + fi + sleep 0.1 +done +port=$(cat ${test_tmpdir}/httpd-port) +echo "http://127.0.0.1:${port}" > ${test_tmpdir}/httpd-address +echo "$child_pid" > ${test_tmpdir}/httpd-pid