[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#859470: unblock: flatpak/0.8.5-1



Package: release.debian.org
Severity: normal
User: release.debian.org@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 <smcv@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, &current_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, &current_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 <smcv@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

Reply to: