Author: renodr
Date: Sat Jun 29 12:32:58 2019
New Revision: 3945

Log:
Add GVFS Security Patch

Added:
   trunk/gvfs/gvfs-1.40.1-fix_security_vulnerabilities-1.patch

Added: trunk/gvfs/gvfs-1.40.1-fix_security_vulnerabilities-1.patch
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ trunk/gvfs/gvfs-1.40.1-fix_security_vulnerabilities-1.patch Sat Jun 29 
12:32:58 2019        (r3945)
@@ -0,0 +1,511 @@
+Submitted By:            Douglas R. Reno <renodr at linuxfromscratch dot org>
+Date:                    2019-06-29
+Initial Package Version: 1.40.1
+Upstream Status:         Applied
+Origin:                  Upstream
+Description:             Fixes four security vulnerabilities in GVFS, two rated
+                         as High and two as Critical. The IDs are 
CVE-2019-12795,
+                         CVE-2019-12447, CVE-2019-12448, and CVE-2019-12449. In
+                         addition, fix the AFP backend for anyone who uses it
+                         since Apple iOS devices beyond 2017 use a UUID longer
+                         than 40 characters.
+
+diff -Naurp gvfs-1.40.1.orig/common/gmountsource.c 
gvfs-1.40.1/common/gmountsource.c
+--- gvfs-1.40.1.orig/common/gmountsource.c     2019-04-09 01:36:07.000000000 
-0500
++++ gvfs-1.40.1/common/gmountsource.c  2019-06-29 13:37:36.962027478 -0500
+@@ -146,8 +146,8 @@ typedef struct AskSyncData AskSyncData;
+ struct AskSyncData {
+ 
+   /* For sync calls */
+-  GMutex mutex;
+-  GCond cond;
++  GMainContext *context;
++  GMainLoop *loop;
+ 
+   /* results: */
+   GAsyncResult *result;
+@@ -375,10 +375,7 @@ ask_reply_sync  (GObject *source_object,
+ 
+   data->result = g_object_ref (res);
+ 
+-  /* Wake up sync call thread */
+-  g_mutex_lock (&data->mutex);
+-  g_cond_signal (&data->cond);
+-  g_mutex_unlock (&data->mutex);
++  g_main_loop_quit (data->loop);
+ }
+ 
+ gboolean
+@@ -397,11 +394,10 @@ g_mount_source_ask_password (GMountSourc
+   gboolean handled;
+   AskSyncData data;
+ 
+-  memset (&data, 0, sizeof (data));
+-  g_mutex_init (&data.mutex);
+-  g_cond_init (&data.cond);
+-  g_mutex_lock (&data.mutex);
++  data.context = g_main_context_new ();
++  data.loop = g_main_loop_new (data.context, FALSE);
+ 
++  g_main_context_push_thread_default (data.context);
+ 
+   g_mount_source_ask_password_async (source,
+                                      message_string,
+@@ -411,13 +407,7 @@ g_mount_source_ask_password (GMountSourc
+                                      ask_reply_sync,
+                                      &data);
+ 
+-  while (data.result == NULL)
+-    g_cond_wait (&data.cond, &data.mutex);
+-  g_mutex_unlock (&data.mutex);
+-
+-  g_cond_clear (&data.cond);
+-  g_mutex_clear (&data.mutex);
+-
++  g_main_loop_run (data.loop);
+ 
+   handled = g_mount_source_ask_password_finish (source,
+                                                 data.result,
+@@ -427,6 +417,10 @@ g_mount_source_ask_password (GMountSourc
+                                                 domain_out,
+                                               anonymous_out,
+                                               password_save_out);
++
++  g_main_context_pop_thread_default (data.context);
++  g_main_context_unref (data.context);
++  g_main_loop_unref (data.loop);
+   g_object_unref (data.result);
+ 
+   return handled;
+@@ -563,10 +557,10 @@ g_mount_source_ask_question (GMountSourc
+   gboolean handled, aborted;
+   AskSyncData data;
+   
+-  memset (&data, 0, sizeof (data));
+-  g_mutex_init (&data.mutex);
+-  g_cond_init (&data.cond);
+-  g_mutex_lock (&data.mutex);
++  data.context = g_main_context_new ();
++  data.loop = g_main_loop_new (data.context, FALSE);
++
++  g_main_context_push_thread_default (data.context);
+ 
+   g_mount_source_ask_question_async (source,
+                                      message,
+@@ -574,18 +568,16 @@ g_mount_source_ask_question (GMountSourc
+                                      ask_reply_sync,
+                                      &data);
+ 
+-  while (data.result == NULL)
+-    g_cond_wait (&data.cond, &data.mutex);
+-  g_mutex_unlock (&data.mutex);
+-
+-  g_cond_clear (&data.cond);
+-  g_mutex_clear (&data.mutex);
++  g_main_loop_run (data.loop);
+ 
+   handled = g_mount_source_ask_question_finish (source,
+                                                 data.result,
+                                                 &aborted,
+                                                 &choice);
+   
++  g_main_context_pop_thread_default (data.context);
++  g_main_context_unref (data.context);
++  g_main_loop_unref (data.loop);
+   g_object_unref (data.result);
+ 
+   if (aborted_out)
+@@ -833,10 +825,10 @@ g_mount_source_show_processes (GMountSou
+   gboolean handled, aborted;
+   AskSyncData data;
+ 
+-  memset (&data, 0, sizeof (data));
+-  g_mutex_init (&data.mutex);
+-  g_cond_init (&data.cond);
+-  g_mutex_lock (&data.mutex);
++  data.context = g_main_context_new ();
++  data.loop = g_main_loop_new (data.context, FALSE);
++
++  g_main_context_push_thread_default (data.context);
+ 
+   g_mount_source_show_processes_async (source,
+                                        message,
+@@ -845,18 +837,16 @@ g_mount_source_show_processes (GMountSou
+                                        ask_reply_sync,
+                                        &data);
+ 
+-  while (data.result == NULL)
+-    g_cond_wait (&data.cond, &data.mutex);
+-  g_mutex_unlock (&data.mutex);
+-
+-  g_cond_clear (&data.cond);
+-  g_mutex_clear (&data.mutex);
++  g_main_loop_run (data.loop);
+ 
+   handled = g_mount_source_show_processes_finish (source,
+                                                   data.result,
+                                                   &aborted,
+                                                   &choice);
+ 
++  g_main_context_pop_thread_default (data.context);
++  g_main_context_unref (data.context);
++  g_main_loop_unref (data.loop);
+   g_object_unref (data.result);
+ 
+   if (aborted_out)
+diff -Naurp gvfs-1.40.1.orig/daemon/gvfsafpconnection.c 
gvfs-1.40.1/daemon/gvfsafpconnection.c
+--- gvfs-1.40.1.orig/daemon/gvfsafpconnection.c        2019-04-09 
01:36:07.000000000 -0500
++++ gvfs-1.40.1/daemon/gvfsafpconnection.c     2019-06-29 13:28:17.228547773 
-0500
+@@ -515,6 +515,12 @@ g_vfs_afp_command_put_pascal (GVfsAfpCom
+ {
+   size_t len;
+ 
++  if (str == NULL)
++  {
++     g_vfs_afp_command_put_byte (comm, 0);
++     return;
++  }
++
+   len = MIN (strlen (str), 256);
+ 
+   g_vfs_afp_command_put_byte (comm, len);
+diff -Naurp gvfs-1.40.1.orig/daemon/gvfsbackendadmin.c 
gvfs-1.40.1/daemon/gvfsbackendadmin.c
+--- gvfs-1.40.1.orig/daemon/gvfsbackendadmin.c 2019-04-09 01:36:07.000000000 
-0500
++++ gvfs-1.40.1/daemon/gvfsbackendadmin.c      2019-06-29 14:15:39.601315566 
-0500
+@@ -42,6 +42,8 @@
+ #include "gvfsjobopenforwrite.h"
+ #include "gvfsjobqueryattributes.h"
+ #include "gvfsjobqueryinfo.h"
++#include "gvfsjobqueryinforead.h"
++#include "gvfsjobqueryinfowrite.h"
+ #include "gvfsjobread.h"
+ #include "gvfsjobseekread.h"
+ #include "gvfsjobseekwrite.h"
+@@ -180,19 +182,6 @@ do_query_info (GVfsBackend *backend,
+   if (error != NULL)
+     goto out;
+ 
+-  /* Override read/write flags, since the above call will use access()
+-   * to determine permissions, which does not honor our privileged
+-   * capabilities.
+-   */
+-  g_file_info_set_attribute_boolean (real_info,
+-                                     G_FILE_ATTRIBUTE_ACCESS_CAN_READ, TRUE);
+-  g_file_info_set_attribute_boolean (real_info,
+-                                     G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, TRUE);
+-  g_file_info_set_attribute_boolean (real_info,
+-                                     G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE, 
TRUE);
+-  g_file_info_set_attribute_boolean (real_info,
+-                                     G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME, 
TRUE);
+-
+   g_file_info_copy_into (real_info, info);
+   g_object_unref (real_info);
+ 
+@@ -201,6 +190,55 @@ do_query_info (GVfsBackend *backend,
+ }
+ 
+ static void
++do_query_info_on_read (GVfsBackend *backend,
++                       GVfsJobQueryInfoRead *query_info_job,
++                       GVfsBackendHandle handle,
++                       GFileInfo *info,
++                       GFileAttributeMatcher *matcher)
++{
++   GVfsJob *job = G_VFS_JOB (query_info_job);
++   GFileInputStream *stream = handle;
++   GError *error = NULL;
++   GFileInfo *real_info;
++
++   real_info = g_file_input_stream_query_info (stream, 
query_info_job->attributes,
++                                               job->cancellable, &error);
++
++   if (error != NULL)
++      goto out;
++
++   g_file_info_copy_into (real_info, info);
++   g_object_unref (real_info);
++
++out:
++   complete_job (job, error);
++}
++static void
++do_query_info_on_write (GVfsBackend *backend,
++                        GVfsJobQueryInfoWrite *query_info_job,
++                        GVfsBackendHandle handle,
++                        GFileInfo *info,
++                        GFileAttributeMatcher *matcher)
++{
++   GVfsJob *job = G_VFS_JOB (query_info_job);
++   GFileOutputStream *stream = handle;
++   GError *error = NULL;
++   GFileInfo *real_info;
++
++   real_info = g_file_output_stream_query_info (stream, 
query_info_job->attributes,
++                                                job->cancellable, &error);
++
++   if (error != NULL)
++      goto out;
++
++   g_file_info_copy_into (real_info, info);
++   g_object_unref (real_info);
++
++out:
++   complete_job (job, error);
++}
++
++static void
+ do_close_write (GVfsBackend *backend,
+                 GVfsJobCloseWrite *close_write_job,
+                 GVfsBackendHandle handle)
+@@ -771,6 +809,51 @@ do_move (GVfsBackend *backend,
+ }
+ 
+ static void
++do_pull (GVfsBackend *backend,
++         GVfsJobPull *pull_job,
++         const char *source,
++         const char *local_path,
++         GFileCopyFlags flags,
++         gboolean remove_source,
++         GFileProgressCallback progress_callback,
++         gpointer progress_callback_data)
++{
++   GVfsBackendAdmin *self = G_VFS_BACKEND_ADMIN (backend);
++   GVfsJob *job = G_VFS_JOB (pull_job);
++   GError *error = NULL;
++   GFile *src_file, *dst_file;
++
++   /* Pull method is necessary when user/group needs to be restored, return
++    * G_IO_ERROR_NOT_SUPPORTED in other cases to proceed with the fallback 
code.
++    */
++   if (!(flags & G_FILE_COPY_ALL_METADATA))
++   {
++      g_vfs_job_failed_literal (G_VFS_JOB (job), G_IO_ERROR,
++                                G_IO_ERROR_NOT_SUPPORTED,
++                                _("Operation not supported"));
++      return;
++   }
++
++   if (!check_permission (self, job))
++      return;
++
++   src_file = g_file_new_for_path (source);
++   dst_file = g_file_new_for_path (local_path);
++
++   if (remove_source)
++      g_file_move (src_file, dst_file, flags, job->cancellable,
++                   progress_callback, progress_callback_data, &error);
++   else
++      g_file_copy (src_file, dst_file, flags, job->cancellable,
++                   progress_callback, progress_callback_data, &error);
++
++   g_object_unref (src_file);
++   g_object_unref (dst_file);
++
++   complete_job (job, error);
++}
++
++static void
+ do_query_settable_attributes (GVfsBackend *backend,
+                               GVfsJobQueryAttributes *query_job,
+                               const char *filename)
+@@ -868,6 +951,8 @@ g_vfs_backend_admin_class_init (GVfsBack
+   backend_class->mount = do_mount;
+   backend_class->open_for_read = do_open_for_read;
+   backend_class->query_info = do_query_info;
++  backend_class->query_info_on_read = do_query_info_on_read;
++  backend_class->query_info_on_write = do_query_info_on_write;
+   backend_class->read = do_read;
+   backend_class->create = do_create;
+   backend_class->append_to = do_append_to;
+@@ -888,6 +973,7 @@ g_vfs_backend_admin_class_init (GVfsBack
+   backend_class->set_attribute = do_set_attribute;
+   backend_class->delete = do_delete;
+   backend_class->move = do_move;
++  backend_class->pull = do_pull;
+   backend_class->query_settable_attributes = do_query_settable_attributes;
+   backend_class->query_writable_namespaces = do_query_writable_namespaces;
+ }
+@@ -913,7 +999,8 @@ g_vfs_backend_admin_init (GVfsBackendAdm
+ 
+ #define REQUIRED_CAPS (CAP_TO_MASK(CAP_FOWNER) | \
+                        CAP_TO_MASK(CAP_DAC_OVERRIDE) | \
+-                       CAP_TO_MASK(CAP_DAC_READ_SEARCH))
++                       CAP_TO_MASK(CAP_DAC_READ_SEARCH) | \
++                       CAP_TO_MASK(CAP_CHOWN))
+ 
+ static void
+ acquire_caps (uid_t uid)
+@@ -921,13 +1008,14 @@ acquire_caps (uid_t uid)
+   struct __user_cap_header_struct hdr;
+   struct __user_cap_data_struct data;
+ 
+-  /* Tell kernel not clear capabilities when dropping root */
+-  if (prctl (PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0)
+-    g_error ("prctl(PR_SET_KEEPCAPS) failed");
+-
+-  /* Drop root uid, but retain the required permitted caps */
+-  if (setuid (uid) < 0)
+-    g_error ("unable to drop privs");
++  /* Set EUID to user to make dbus work */
++  if (seteuid (uid) < 0)
++     g_error ("Unable to drop privileges");
++
++  /* Set fsuid to still behave like root when working with files */
++  setfsuid (0);
++  if (setfsuid (-1) != 0)
++     g_error ("setfsuid failed");
+ 
+   memset (&hdr, 0, sizeof(hdr));
+   hdr.version = _LINUX_CAPABILITY_VERSION;
+diff -Naurp gvfs-1.40.1.orig/daemon/gvfsbackendafc.c 
gvfs-1.40.1/daemon/gvfsbackendafc.c
+--- gvfs-1.40.1.orig/daemon/gvfsbackendafc.c   2019-04-09 01:36:07.000000000 
-0500
++++ gvfs-1.40.1/daemon/gvfsbackendafc.c        2019-06-29 13:40:12.774668154 
-0500
+@@ -9,7 +9,6 @@
+ 
+ #include <limits.h>
+ #include <stdint.h>
+-#include <stdio.h>
+ #include <string.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+@@ -73,7 +72,7 @@ typedef struct {
+ struct _GVfsBackendAfc {
+   GVfsBackend backend;
+ 
+-  char uuid[41];
++  char *uuid;
+   char *service;
+   char *model;
+   gboolean connected;
+@@ -472,16 +471,11 @@ g_vfs_backend_afc_mount (GVfsBackend *ba
+     {
+       g_vfs_job_failed (G_VFS_JOB (job),
+                         G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+-                        _("Invalid mount spec"));
+-      return;
+-    }
+-  if (G_UNLIKELY(sscanf(str, "%40s", (char *) &self->uuid) < 1))
+-    {
+-      g_vfs_job_failed (G_VFS_JOB(job), G_IO_ERROR, G_IO_ERROR_FAILED,
+                         _("Invalid AFC location: must be in the form of "
+                           "afc://uuid:port-number"));
+       return;
+     }
++  self->uuid = g_strdup (str);
+ 
+   str = g_mount_spec_get (spec, "port");
+   if (str == NULL)
+@@ -519,9 +513,7 @@ g_vfs_backend_afc_mount (GVfsBackend *ba
+   display_name = NULL;
+ 
+   real_spec = g_mount_spec_new ("afc");
+-  tmp = g_strdup_printf ("%40s", (char *) &self->uuid);
+-  g_mount_spec_set (real_spec, "host", tmp);
+-  g_free (tmp);
++  g_mount_spec_set (real_spec, "host", self->uuid);
+ 
+   /* INFO: Don't ever set the DefaultPort again or everything goes crazy */
+   if (virtual_port != VIRTUAL_PORT_AFC)
+@@ -2752,6 +2744,8 @@ g_vfs_backend_afc_finalize (GObject *obj
+       self->force_umount_id = 0;
+   }
+ 
++  g_free (self->uuid);
++
+   if (G_OBJECT_CLASS(g_vfs_backend_afc_parent_class)->finalize)
+     (*G_OBJECT_CLASS(g_vfs_backend_afc_parent_class)->finalize) (obj);
+ }
+diff -Naurp gvfs-1.40.1.orig/daemon/gvfsdaemon.c 
gvfs-1.40.1/daemon/gvfsdaemon.c
+--- gvfs-1.40.1.orig/daemon/gvfsdaemon.c       2019-04-09 01:36:07.000000000 
-0500
++++ gvfs-1.40.1/daemon/gvfsdaemon.c    2019-06-29 14:13:55.078149180 -0500
+@@ -79,6 +79,7 @@ struct _GVfsDaemon
+   
+   gint mount_counter;
+   
++  GDBusAuthObserver *auth_observer;
+   GDBusConnection *conn;
+   GVfsDBusDaemon *daemon_skeleton;
+   GVfsDBusMountable *mountable_skeleton;
+@@ -171,7 +172,9 @@ g_vfs_daemon_finalize (GObject *object)
+     }
+   if (daemon->conn != NULL)
+     g_object_unref (daemon->conn);
+-  
++  if (daemon->auth_observer != NULL)
++    g_object_unref (daemon->auth_observer);
++
+   g_hash_table_destroy (daemon->registered_paths);
+   g_hash_table_destroy (daemon->client_connections);
+   g_mutex_clear (&daemon->lock);
+@@ -236,6 +239,51 @@ name_vanished_handler (GDBusConnection *
+   daemon->lost_main_daemon = TRUE;
+ }
+ 
++/*
++ * Authentication observer signal handler that rejects all authentication
++ * mechanisms except for EXTERNAL (credentials-passing), which is the
++ * recommended authentication mechanism for all AF_UNIX sockets.
++ */
++static gboolean
++allow_mechanism_cb (GDBusAuthObserver *observer,
++                    const gchar *mechanism,
++                    G_GNUC_UNUSED gpointer user_data)
++{
++   if (g_strcmp0 (mechanism, "EXTERNAL") == 0)
++      return TRUE;
++
++   return FALSE;
++}
++
++/*
++ * Authentication observer signal handler that authorizes connections
++ * from the same uid as this process. This matches the behavior of a 
++ * libdbus DBusServer/DBusConnection when no DBusAllowUnixUserFunction
++ * has been set, but is not the default in GDBus.
++ */
++static gboolean
++authorize_authenticated_peer_cb (GDBusAuthObserver *observer,
++                                 G_GNUC_UNUSED GIOStream *stream,
++                                 GCredentials *credentials,
++                                 G_GNUC_UNUSED gpointer user_data)
++{
++   gboolean authorized = FALSE;
++
++   if (credentials != NULL)
++   {
++      GCredentials *own_credentials;
++
++      own_credentials = g_credentials_new () ;
++
++      if (g_credentials_is_same_user (credentials, own_credentials, NULL))
++         authorized = TRUE;
++
++      g_object_unref (own_credentials);
++   }
++
++   return authorized;
++}
++
+ static void
+ g_vfs_daemon_init (GVfsDaemon *daemon)
+ {
+@@ -265,6 +313,9 @@ g_vfs_daemon_init (GVfsDaemon *daemon)
+ 
+   daemon->conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
+   g_assert (daemon->conn != NULL);
++  daemon->auth_observer = g_dbus_auth_observer_new ();
++  g_signal_connect (daemon->auth_observer, "allow-mechanism", G_CALLBACK 
(allow_mechanism_cb), NULL);
++  g_signal_connect (daemon->auth_observer, "authorized-authenticated-peer", 
G_CALLBACK (authorize_authenticated_peer_cb), NULL);
+ 
+   daemon->daemon_skeleton = gvfs_dbus_daemon_skeleton_new ();
+   g_signal_connect (daemon->daemon_skeleton, "handle-get-connection", 
G_CALLBACK (handle_get_connection), daemon);
+@@ -876,7 +927,7 @@ handle_get_connection (GVfsDBusDaemon *o
+   server = g_dbus_server_new_sync (address1,
+                                    G_DBUS_SERVER_FLAGS_NONE,
+                                    guid,
+-                                   NULL, /* GDBusAuthObserver */
++                                   daemon->auth_observer,
+                                    NULL, /* GCancellable */
+                                    &error);
+   g_free (guid);
-- 
http://lists.linuxfromscratch.org/listinfo/patches
FAQ: http://www.linuxfromscratch.org/blfs/faq.html
Unsubscribe: See the above information page

Reply via email to