[gimp] Bug 767873 - (CVE-2016-4994) Multiple Use-After-Free when parsing...



commit 6d804bf9ae77bc86a0a97f9b944a129844df9395
Author: Shmuel H <shmuelgimp gmail com>
Date:   Mon Jun 20 17:14:41 2016 +0300

    Bug 767873 - (CVE-2016-4994) Multiple Use-After-Free when parsing...
    
    ...XCF channel and layer properties
    
    The properties PROP_ACTIVE_LAYER, PROP_FLOATING_SELECTION,
    PROP_ACTIVE_CHANNEL saves the current object pointer the @info
    structure. Others like PROP_SELECTION (for channel) and
    PROP_GROUP_ITEM (for layer) will delete the current object and create
    a new object, leaving the pointers in @info invalid (dangling).
    
    Therefore, if a property from the first type will come before the
    second, the result will be an UaF in the last lines of xcf_load_image
    (when it actually using the pointers from @info).
    
    I wasn't able to exploit this bug because that
    g_object_instance->c_class gets cleared by the last g_object_unref and
    GIMP_IS_{LAYER,CHANNEL} detects that and return FALSE.

 app/xcf/xcf-load.c |   29 +++++++++++++++++++++++++++++
 1 files changed, 29 insertions(+), 0 deletions(-)
---
diff --git a/app/xcf/xcf-load.c b/app/xcf/xcf-load.c
index f48558a..244d5c2 100644
--- a/app/xcf/xcf-load.c
+++ b/app/xcf/xcf-load.c
@@ -1141,6 +1141,18 @@ xcf_load_layer_props (XcfInfo    *info,
         case PROP_GROUP_ITEM:
           {
             GimpLayer *group;
+            gboolean   is_active_layer;
+
+            /* We're going to delete *layer, Don't leave its pointers
+             * in @info.  After that, we'll restore them back with the
+             * new pointer. See bug #767873.
+             */
+            is_active_layer = (*layer == info->active_layer);
+            if (is_active_layer)
+              info->active_layer = NULL;
+
+            if (*layer == info->floating_sel)
+              info->floating_sel = NULL;
 
             group = gimp_group_layer_new (image);
 
@@ -1150,6 +1162,13 @@ xcf_load_layer_props (XcfInfo    *info,
             g_object_ref_sink (*layer);
             g_object_unref (*layer);
             *layer = group;
+
+            if (is_active_layer)
+              info->active_layer = *layer;
+
+            /* Don't restore info->floating_sel because group layers
+             * can't be floating selections
+             */
           }
           break;
 
@@ -1220,6 +1239,12 @@ xcf_load_channel_props (XcfInfo      *info,
           {
             GimpChannel *mask;
 
+            /* We're going to delete *channel, Don't leave its pointer
+             * in @info. See bug #767873.
+             */
+            if (*channel == info->active_channel)
+              info->active_channel = NULL;
+
             mask =
               gimp_selection_new (image,
                                   gimp_item_get_width  (GIMP_ITEM (*channel)),
@@ -1234,6 +1259,10 @@ xcf_load_channel_props (XcfInfo      *info,
             *channel = mask;
             (*channel)->boundary_known = FALSE;
             (*channel)->bounds_known   = FALSE;
+
+            /* Don't restore info->active_channel because the
+             * selection can't be the active channel
+             */
           }
           break;
 


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