1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
|
commit ebf0b569a63f15b5dc7532f16936104af1e09f02
Author: Andrzej Hunt <andrzej@ahunt.org>
Date: Tue Jul 16 18:30:28 2024 +0200
xcf: don't use potentially dangling pointer in xcf_load_layer_mask
layer_mask points to the original mask created by xcf_load_layer_mask. We copy
this pointer into channel, and xcf_load_channel_props can overwrite this
pointer and free the original mask. If this happens, layer_mask points to
the now-freed original mask, and should not be used.
Therefore we need to change later parts of xcf_load_layer_mask to use channel
instead of layer_mask. Additionally, we add a block and move layer_mask into
this block to guarantee that layer_mask cannot be used after it has
potentially been freed.
Adjustments by Jacob Boerema:
Follow GIMP's code style regarding variables, comment style and
position of braces
See also ASAN output below:
==5247==ERROR: AddressSanitizer: heap-use-after-free on address 0x615000010fd0 at pc 0x7f4e2dbbf31b bp 0x7ffca8a95cd0 sp 0x7ffca8a95cc8
READ of size 8 at 0x615000010fd0 thread T0
#0 0x7f4e2dbbf31a in g_type_check_instance_cast /home/ahunt/git/glib/_build/../gobject/gtype.c:4117:26
#1 0xb200fe in xcf_load_layer_mask /home/ahunt/git/gimp/app/xcf/xcf-load.c:2305:52
#2 0xb18eea in xcf_load_layer /home/ahunt/git/gimp/app/xcf/xcf-load.c:2133:20
#3 0xb13d91 in xcf_load_image /home/ahunt/git/gimp/app/xcf/xcf-load.c:499:15
#4 0xb11deb in xcf_load_stream /home/ahunt/git/gimp/app/xcf/xcf.c:305:19
#5 0x619dfd in LLVMFuzzerTestOneInput /home/ahunt/git/gimp/app/fuzzers/xcf_fuzzer.c:50:17
#6 0x51d364 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /home/abuild/rpmbuild/BUILD/llvm-12.0.0.src/build/../projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:599:15
#7 0x506fe2 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) /home/abuild/rpmbuild/BUILD/llvm-12.0.0.src/build/../projects/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:323:6
#8 0x50d350 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /home/abuild/rpmbuild/BUILD/llvm-12.0.0.src/build/../projects/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:856:9
#9 0x5373a2 in main /home/abuild/rpmbuild/BUILD/llvm-12.0.0.src/build/../projects/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
#10 0x7f4e2c84c349 in __libc_start_main (/lib64/libc.so.6+0x24349)
#11 0x4e0779 in _start /home/abuild/rpmbuild/BUILD/glibc-2.26/csu/../sysdeps/x86_64/start.S:120
0x615000010fd0 is located 336 bytes inside of 504-byte region [0x615000010e80,0x615000011078)
freed by thread T0 here:
#0 0x5e8562 in free /home/abuild/rpmbuild/BUILD/llvm-12.0.0.src/build/../projects/compiler-rt/lib/asan/asan_malloc_linux.cpp:127:3
#1 0x7f4e2d76ce08 in g_free /home/ahunt/git/glib/_build/../glib/gmem.c:199:3
#2 0x7f4e2d797a6b in g_slice_free1 /home/ahunt/git/glib/_build/../glib/gslice.c:1183:7
#3 0x7f4e2dbb7b04 in g_type_free_instance /home/ahunt/git/glib/_build/../gobject/gtype.c:2008:5
#4 0x7f4e2db8fe3a in g_object_unref /home/ahunt/git/glib/_build/../gobject/gobject.c:3604:11
#5 0xb22fff in xcf_load_channel_props /home/ahunt/git/gimp/app/xcf/xcf-load.c:1738:13
#6 0xb20037 in xcf_load_layer_mask /home/ahunt/git/gimp/app/xcf/xcf-load.c:2292:9
#7 0xb18eea in xcf_load_layer /home/ahunt/git/gimp/app/xcf/xcf-load.c:2133:20
#8 0xb13d91 in xcf_load_image /home/ahunt/git/gimp/app/xcf/xcf-load.c:499:15
#9 0xb11deb in xcf_load_stream /home/ahunt/git/gimp/app/xcf/xcf.c:305:19
#10 0x619dfd in LLVMFuzzerTestOneInput /home/ahunt/git/gimp/app/fuzzers/xcf_fuzzer.c:50:17
#11 0x51d364 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /home/abuild/rpmbuild/BUILD/llvm-12.0.0.src/build/../projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:599:15
#12 0x506fe2 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) /home/abuild/rpmbuild/BUILD/llvm-12.0.0.src/build/../projects/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:323:6
#13 0x50d350 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /home/abuild/rpmbuild/BUILD/llvm-12.0.0.src/build/../projects/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:856:9
#14 0x5373a2 in main /home/abuild/rpmbuild/BUILD/llvm-12.0.0.src/build/../projects/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
#15 0x7f4e2c84c349 in __libc_start_main (/lib64/libc.so.6+0x24349)
previously allocated by thread T0 here:
#0 0x5e87cd in malloc /home/abuild/rpmbuild/BUILD/llvm-12.0.0.src/build/../projects/compiler-rt/lib/asan/asan_malloc_linux.cpp:145:3
#1 0x7f4e2d76ccf2 in g_malloc /home/ahunt/git/glib/_build/../glib/gmem.c:106:13
#2 0x7f4e2d7972e0 in g_slice_alloc /home/ahunt/git/glib/_build/../glib/gslice.c:1072:11
#3 0x7f4e2d7978ae in g_slice_alloc0 /home/ahunt/git/glib/_build/../glib/gslice.c:1098:18
#4 0x7f4e2dbb6e0a in g_type_create_instance /home/ahunt/git/glib/_build/../gobject/gtype.c:1911:17
#5 0x7f4e2db9215e in g_object_new_internal /home/ahunt/git/glib/_build/../gobject/gobject.c:1945:24
#6 0x7f4e2db91d1f in g_object_new_valist /home/ahunt/git/glib/_build/../gobject/gobject.c:2288:16
#7 0x7f4e2db90e8b in g_object_new /home/ahunt/git/glib/_build/../gobject/gobject.c:1788:12
#8 0xdb69e0 in gimp_item_new /home/ahunt/git/gimp/app/core/gimpitem.c:723:10
#9 0xce11c8 in gimp_drawable_new /home/ahunt/git/gimp/app/core/gimpdrawable.c:1067:14
#10 0xddf5d8 in gimp_layer_mask_new /home/ahunt/git/gimp/app/core/gimplayermask.c:254:5
#11 0xb1ffc5 in xcf_load_layer_mask /home/ahunt/git/gimp/app/xcf/xcf-load.c:2279:31
#12 0xb18eea in xcf_load_layer /home/ahunt/git/gimp/app/xcf/xcf-load.c:2133:20
#13 0xb13d91 in xcf_load_image /home/ahunt/git/gimp/app/xcf/xcf-load.c:499:15
#14 0xb11deb in xcf_load_stream /home/ahunt/git/gimp/app/xcf/xcf.c:305:19
#15 0x619dfd in LLVMFuzzerTestOneInput /home/ahunt/git/gimp/app/fuzzers/xcf_fuzzer.c:50:17
#16 0x51d364 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /home/abuild/rpmbuild/BUILD/llvm-12.0.0.src/build/../projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:599:15
#17 0x506fe2 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) /home/abuild/rpmbuild/BUILD/llvm-12.0.0.src/build/../projects/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:323:6
#18 0x50d350 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /home/abuild/rpmbuild/BUILD/llvm-12.0.0.src/build/../projects/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:856:9
#19 0x5373a2 in main /home/abuild/rpmbuild/BUILD/llvm-12.0.0.src/build/../projects/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
#20 0x7f4e2c84c349 in __libc_start_main (/lib64/libc.so.6+0x24349)
SUMMARY: AddressSanitizer: heap-use-after-free /home/ahunt/git/glib/_build/../gobject/gtype.c:4117:26 in g_type_check_instance_cast
Shadow bytes around the buggy address:
0x0c2a7fffa1a0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a7fffa1b0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a7fffa1c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a7fffa1d0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a7fffa1e0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
=>0x0c2a7fffa1f0: fd fd fd fd fd fd fd fd fd fd[fd]fd fd fd fd fd
0x0c2a7fffa200: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
0x0c2a7fffa210: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a7fffa220: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a7fffa230: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a7fffa240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==5247==ABORTING
./crash-0507799c3e4291570e060f53332b58b8a96f95e5
(cherry picked from commit fe26086e16943860f3852120f546ce913a7a73ee)
# Conflicts:
# app/xcf/xcf-load.c
diff --git a/app/xcf/xcf-load.c b/app/xcf/xcf-load.c
index da196bcdb2..41e582719a 100644
--- a/app/xcf/xcf-load.c
+++ b/app/xcf/xcf-load.c
@@ -102,7 +102,8 @@ static gboolean xcf_check_layer_props (XcfInfo *info,
gboolean *is_text_layer);
static gboolean xcf_load_channel_props (XcfInfo *info,
GimpImage *image,
- GimpChannel **channel);
+ GimpChannel **channel,
+ gboolean is_mask);
static gboolean xcf_load_prop (XcfInfo *info,
PropType *prop_type,
guint32 *prop_size);
@@ -1656,7 +1657,8 @@ xcf_check_layer_props (XcfInfo *info,
static gboolean
xcf_load_channel_props (XcfInfo *info,
GimpImage *image,
- GimpChannel **channel)
+ GimpChannel **channel,
+ gboolean is_mask)
{
PropType prop_type;
guint32 prop_size;
@@ -1679,6 +1681,14 @@ xcf_load_channel_props (XcfInfo *info,
{
GimpChannel *mask;
+ if (is_mask)
+ {
+ /* PROP_SELECTION is not valid for masks, and we have to avoid
+ * overwriting the channel.
+ */
+ continue;
+ }
+
/* We're going to delete *channel, Don't leave its pointer
* in @info. See bug #767873.
*/
@@ -2151,7 +2161,7 @@ xcf_load_channel (XcfInfo *info,
return NULL;
/* read in the channel properties */
- if (! xcf_load_channel_props (info, image, &channel))
+ if (! xcf_load_channel_props (info, image, &channel, FALSE))
goto error;
xcf_progress_update (info);
@@ -2238,7 +2248,7 @@ xcf_load_layer_mask (XcfInfo *info,
/* read in the layer_mask properties */
channel = GIMP_CHANNEL (layer_mask);
- if (! xcf_load_channel_props (info, image, &channel))
+ if (! xcf_load_channel_props (info, image, &channel, TRUE))
goto error;
xcf_progress_update (info);
|