Blob Blame Raw
From efd698210389f6be52c04117ca8615971ec009fc Mon Sep 17 00:00:00 2001
From: Alexander Larsson <alexl@redhat.com>
Date: Fri, 30 Nov 2018 10:30:20 +0100
Subject: [PATCH] OCI: Use system helper to generate summary for OCI remotes

The OCI support relies on downloading a json index and converting it
to a ostree-style summary, which we the use in all sorts of operations
in the client code. Currently this happens in the user code, which means
that it will fail (due to permissions) in the system installation case.

We could do the conversion as the user, but when eventually installing
something the system-helper will anyway do this download and
conversion, so that would only double the work and risk things going out
of sync. Also, the OCI index is not gpg signed, so we can't realy on
downloads done as the user.

So, the solution done here is to add a GenerateOciSummary
system-helper call which we use instead of directly generating the
oci summary.

This fixes https://github.com/flatpak/flatpak/issues/2350
---
 common/flatpak-dir-private.h          |  5 ++
 common/flatpak-dir.c                  | 94 +++++++++++++++++++--------
 data/org.freedesktop.Flatpak.xml      |  5 ++
 system-helper/flatpak-system-helper.c | 54 ++++++++++++++-
 4 files changed, 131 insertions(+), 27 deletions(-)

diff --git a/common/flatpak-dir-private.h b/common/flatpak-dir-private.h
index da7ea8e3..4d47385a 100644
--- a/common/flatpak-dir-private.h
+++ b/common/flatpak-dir-private.h
@@ -720,6 +720,11 @@ FlatpakRemoteState * flatpak_dir_get_remote_state_for_summary (FlatpakDir   *sel
                                                                GBytes       *opt_summary_sig,
                                                                GCancellable *cancellable,
                                                                GError      **error);
+gboolean flatpak_dir_remote_make_oci_summary (FlatpakDir   *self,
+                                              const char   *remote,
+                                              GBytes      **out_summary,
+                                              GCancellable *cancellable,
+                                              GError      **error);
 FlatpakRemoteState * flatpak_dir_get_remote_state_optional (FlatpakDir   *self,
                                                             const char   *remote,
                                                             GCancellable *cancellable,
diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c
index 0809a42b..4698aa4a 100644
--- a/common/flatpak-dir.c
+++ b/common/flatpak-dir.c
@@ -1385,6 +1385,22 @@ flatpak_dir_system_helper_call_update_summary (FlatpakDir   *self,
   return ret != NULL;
 }
 
+static gboolean
+flatpak_dir_system_helper_call_generate_oci_summary (FlatpakDir   *self,
+                                                     const gchar  *arg_origin,
+                                                     const gchar  *arg_installation,
+                                                     GCancellable *cancellable,
+                                                     GError      **error)
+{
+  g_autoptr(GVariant) ret =
+    flatpak_dir_system_helper_call (self, "GenerateOciSummary",
+                                    g_variant_new ("(ss)",
+                                                   arg_origin,
+                                                   arg_installation),
+                                    cancellable, error);
+  return ret != NULL;
+}
+
 static OstreeRepo *
 system_ostree_repo_new (GFile *repodir)
 {
@@ -9104,7 +9120,7 @@ flatpak_dir_cache_summary (FlatpakDir *self,
   G_UNLOCK (cache);
 }
 
-static gboolean
+gboolean
 flatpak_dir_remote_make_oci_summary (FlatpakDir   *self,
                                      const char   *remote,
                                      GBytes      **out_summary,
@@ -9119,42 +9135,68 @@ flatpak_dir_remote_make_oci_summary (FlatpakDir   *self,
   g_autoptr(GError) local_error = NULL;
   g_autoptr(GMappedFile) mfile = NULL;
   g_autoptr(GBytes) cache_bytes = NULL;
+  g_autoptr(GBytes) summary_bytes = NULL;
 
-  self_name = flatpak_dir_get_name (self);
-
-  index_cache = flatpak_dir_update_oci_index (self, remote, &index_uri, cancellable, error);
-  if (index_cache == NULL)
-    return FALSE;
+  if (flatpak_dir_use_system_helper (self, NULL))
+    {
+      const char *installation = flatpak_dir_get_id (self);
 
-  summary_cache = flatpak_dir_get_oci_summary_location (self, remote, error);
-  if (summary_cache == NULL)
-    return FALSE;
+      if (!flatpak_dir_system_helper_call_generate_oci_summary (self, remote,
+                                                                installation ? installation : "",
+                                                                cancellable, error))
+        return FALSE;
 
-  if (check_destination_mtime (index_cache, summary_cache, cancellable))
+      summary_cache = flatpak_dir_get_oci_summary_location (self, remote, error);
+      if (summary_cache == NULL)
+        return FALSE;
+    }
+  else
     {
-      mfile = g_mapped_file_new (flatpak_file_get_path_cached (summary_cache), FALSE, NULL);
-      if (mfile)
+      self_name = flatpak_dir_get_name (self);
+
+      index_cache = flatpak_dir_update_oci_index (self, remote, &index_uri, cancellable, error);
+      if (index_cache == NULL)
+        return FALSE;
+
+      summary_cache = flatpak_dir_get_oci_summary_location (self, remote, error);
+      if (summary_cache == NULL)
+        return FALSE;
+
+      if (!check_destination_mtime (index_cache, summary_cache, cancellable))
         {
-          cache_bytes = g_mapped_file_get_bytes (mfile);
-          *out_summary = g_steal_pointer (&cache_bytes);
+          summary = flatpak_oci_index_make_summary (index_cache, index_uri, cancellable, &local_error);
+          if (summary == NULL)
+            {
+              g_propagate_error (error, g_steal_pointer (&local_error));
+              return FALSE;
+            }
+
+          summary_bytes = g_variant_get_data_as_bytes (summary);
+
+          if (!g_file_replace_contents (summary_cache,
+                                        g_bytes_get_data (summary_bytes, NULL),
+                                        g_bytes_get_size (summary_bytes),
+                                        NULL, FALSE, 0, NULL, cancellable, error))
+            {
+              g_prefix_error (error, _("Failed to write summary cache: "));
+              return FALSE;
+            }
+
+          if (out_summary)
+              *out_summary = g_steal_pointer (&summary_bytes);
           return TRUE;
         }
     }
 
-  summary = flatpak_oci_index_make_summary (index_cache, index_uri, cancellable, &local_error);
-  if (summary == NULL)
+  if (out_summary)
     {
-      g_propagate_error (error, g_steal_pointer (&local_error));
-      return FALSE;
-    }
-
-  *out_summary = g_variant_get_data_as_bytes (summary);
+      mfile = g_mapped_file_new (flatpak_file_get_path_cached (summary_cache), FALSE, error);
+      if (mfile == NULL)
+        return FALSE;
 
-  if (!g_file_replace_contents (summary_cache,
-                                g_bytes_get_data (*out_summary, NULL),
-                                g_bytes_get_size (*out_summary),
-                                NULL, FALSE, 0, NULL, cancellable, NULL))
-    g_warning ("Failed to write summary cache");
+      cache_bytes = g_mapped_file_get_bytes (mfile);
+      *out_summary = g_steal_pointer (&cache_bytes);
+    }
 
   return TRUE;
 }
diff --git a/data/org.freedesktop.Flatpak.xml b/data/org.freedesktop.Flatpak.xml
index 25dc8a02..8b1606c6 100644
--- a/data/org.freedesktop.Flatpak.xml
+++ b/data/org.freedesktop.Flatpak.xml
@@ -144,6 +144,11 @@
       <arg type='s' name='installation' direction='in'/>
     </method>
 
+    <method name="GenerateOciSummary">
+      <arg type='s' name='origin' direction='in'/>
+      <arg type='s' name='installation' direction='in'/>
+    </method>
+
   </interface>
 
 </node>
diff --git a/system-helper/flatpak-system-helper.c b/system-helper/flatpak-system-helper.c
index ce647b6e..24b3ddf9 100644
--- a/system-helper/flatpak-system-helper.c
+++ b/system-helper/flatpak-system-helper.c
@@ -1122,6 +1122,56 @@ handle_update_summary (FlatpakSystemHelper   *object,
   return TRUE;
 }
 
+static gboolean
+handle_generate_oci_summary (FlatpakSystemHelper   *object,
+                             GDBusMethodInvocation *invocation,
+                             const gchar           *arg_origin,
+                             const gchar           *arg_installation)
+{
+  g_autoptr(FlatpakDir) system = NULL;
+  g_autoptr(GError) error = NULL;
+  g_autofree char *new_branch = NULL;
+  g_autofree char *old_branch = NULL;
+  gboolean is_oci;
+
+  g_debug ("GenerateOciSummary %s %s", arg_origin, arg_installation);
+
+  system = dir_get_system (arg_installation, &error);
+  if (system == NULL)
+    {
+      g_dbus_method_invocation_return_gerror (invocation, error);
+      return TRUE;
+    }
+
+  if (!flatpak_dir_ensure_repo (system, NULL, &error))
+    {
+      g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
+                                             "Can't open system repo %s", error->message);
+      return TRUE;
+    }
+
+  is_oci = flatpak_dir_get_remote_oci (system, arg_origin);
+  if (!is_oci)
+    {
+      g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+                                             "%s is not a OCI remote", arg_origin);
+      return TRUE;
+    }
+
+  if (!flatpak_dir_remote_make_oci_summary (system, arg_origin, NULL, NULL, &error))
+    {
+      g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
+                                             "Failed to update OCI summary: %s", error->message);
+      return TRUE;
+    }
+
+
+  flatpak_system_helper_complete_generate_oci_summary (object, invocation);
+
+  return TRUE;
+}
+
+
 static gboolean
 flatpak_authorize_method_handler (GDBusInterfaceSkeleton *interface,
                                   GDBusMethodInvocation  *invocation,
@@ -1250,7 +1300,8 @@ flatpak_authorize_method_handler (GDBusInterfaceSkeleton *interface,
            g_strcmp0 (method_name, "PruneLocalRepo") == 0 ||
            g_strcmp0 (method_name, "EnsureRepo") == 0 ||
            g_strcmp0 (method_name, "RunTriggers") == 0 ||
-           g_strcmp0 (method_name, "UpdateSummary") == 0)
+           g_strcmp0 (method_name, "UpdateSummary") == 0 ||
+           g_strcmp0 (method_name, "GenerateOciSummary") == 0)
     {
       const char *remote;
 
@@ -1321,6 +1372,7 @@ on_bus_acquired (GDBusConnection *connection,
   g_signal_connect (helper, "handle-ensure-repo", G_CALLBACK (handle_ensure_repo), NULL);
   g_signal_connect (helper, "handle-run-triggers", G_CALLBACK (handle_run_triggers), NULL);
   g_signal_connect (helper, "handle-update-summary", G_CALLBACK (handle_update_summary), NULL);
+  g_signal_connect (helper, "handle-generate-oci-summary", G_CALLBACK (handle_generate_oci_summary), NULL);
 
   g_signal_connect (helper, "g-authorize-method",
                     G_CALLBACK (flatpak_authorize_method_handler),
-- 
2.19.1