-
Notifications
You must be signed in to change notification settings - Fork 263
Description
Description
Hello, while performing fuzzing based on the information registered in OSS-Fuzz, a UAF crash was discovered. I would like to share some basic analysis and crash data related to this. (Additionally, this issue does not have a significantly detrimental effect on the program.)
Crash Log
/out/FuzzCUPS -rss_limit_mb=2560 -timeout=25 FuzzCUPS_poc/cups--FuzzCUPS--crash-ec73921dbc52d3ce45efccb47567ba46-2023-07-27-16:03:10 # /tmp/FuzzCUPS_corpus < /dev/null
INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 2666470492
INFO: Loaded 1 modules (10782 inline 8-bit counters): 10782 [0x724ea0, 0x7278be),
INFO: Loaded 1 PC tables (10782 PCs): 10782 [0x7278c0,0x751aa0),
/out/FuzzCUPS: Running 1 inputs 1 time(s) each.
Running: FuzzCUPS_poc/cups--FuzzCUPS--crash-ec73921dbc52d3ce45efccb47567ba46-2023-07-27-16:03:10
=================================================================
==12==ERROR: AddressSanitizer: heap-use-after-free on address 0x61d0000007d0 at pc 0x000000530bd1 bp 0x7ffc688612a0 sp 0x7ffc68860a70
READ of size 72 at 0x61d0000007d0 thread T0
SCARINESS: 54 (multi-byte-read-heap-use-after-free)
#0 0x530bd0 in __asan_memcpy /src/llvm-project/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp:22:3
#1 0x5778d7 in memcpy /usr/include/x86_64-linux-gnu/bits/string_fortified.h:34:10
#2 0x5778d7 in push_stack /src/cups/cups/raster-interpret.c:955:3
#3 0x5778d7 in copy_stack /src/cups/cups/raster-interpret.c:730:10
#4 0x573196 in _cupsRasterExecPS /src/cups/cups/raster-interpret.c
#5 0x56ee5c in LLVMFuzzerTestOneInput /src/cups/fuzzer/FuzzCUPS.c:45:5
#6 0x4406b3 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:611:15
#7 0x42be12 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:324:6
#8 0x4316bc in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:860:9
#9 0x45abf2 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
#10 0x7f677bc91082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee)
#11 0x421fdd in _start (/out/FuzzCUPS+0x421fdd)
DEDUP_TOKEN: __asan_memcpy--memcpy--push_stack
0x61d0000007d0 is located 1872 bytes inside of 2304-byte region [0x61d000000080,0x61d000000980)
freed by thread T0 here:
#0 0x531c4c in __interceptor_realloc /src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:85:3
#1 0x577844 in push_stack /src/cups/cups/raster-interpret.c:944:17
#2 0x577844 in copy_stack /src/cups/cups/raster-interpret.c:730:10
#3 0x573196 in _cupsRasterExecPS /src/cups/cups/raster-interpret.c
#4 0x56ee5c in LLVMFuzzerTestOneInput /src/cups/fuzzer/FuzzCUPS.c:45:5
#5 0x4406b3 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:611:15
#6 0x42be12 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:324:6
#7 0x4316bc in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:860:9
#8 0x45abf2 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
#9 0x7f677bc91082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee)
DEDUP_TOKEN: __interceptor_realloc--push_stack--copy_stack
previously allocated by thread T0 here:
#0 0x531a1e in __interceptor_calloc /src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:77:3
#1 0x570d1b in new_stack /src/cups/cups/raster-interpret.c:899:19
#2 0x570d1b in _cupsRasterExecPS /src/cups/cups/raster-interpret.c:529:13
#3 0x56ee5c in LLVMFuzzerTestOneInput /src/cups/fuzzer/FuzzCUPS.c:45:5
#4 0x4406b3 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:611:15
#5 0x42be12 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:324:6
#6 0x4316bc in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:860:9
#7 0x45abf2 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
#8 0x7f677bc91082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee)
DEDUP_TOKEN: __interceptor_calloc--new_stack--_cupsRasterExecPS
SUMMARY: AddressSanitizer: heap-use-after-free /src/llvm-project/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp:22:3 in __asan_memcpy
Shadow bytes around the buggy address:
0x0c3a7fff80a0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c3a7fff80b0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c3a7fff80c0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c3a7fff80d0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c3a7fff80e0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
=>0x0c3a7fff80f0: fd fd fd fd fd fd fd fd fd fd[fd]fd fd fd fd fd
0x0c3a7fff8100: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c3a7fff8110: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c3a7fff8120: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c3a7fff8130: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c3a7fff8140: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
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
==12==ABORTING
Analyze
From the debugging results, the obj structure was in a freed state at memcpy(temp, obj, sizeof(_cups_ps_obj_t)); in the push_stack function below.
The point at which it is freed seems to be when temp = realloc(st->objs, (size_t)st->alloc_objs * sizeof(_cups_ps_obj_t))) == NULL, as the memory of the heap area pointed to by obj is freed by realloc.
static _cups_ps_obj_t * /* O - New object */
push_stack(_cups_ps_stack_t *st, /* I - Stack */
_cups_ps_obj_t *obj) /* I - Object */
{
_cups_ps_obj_t *temp; /* New object */
if (st->num_objs >= st->alloc_objs)
{
st->alloc_objs += 32;
if ((temp = realloc(st->objs, (size_t)st->alloc_objs *
sizeof(_cups_ps_obj_t))) == NULL)
return (NULL);
st->objs = temp;
memset(temp + st->num_objs, 0, 32 * sizeof(_cups_ps_obj_t));
}
temp = st->objs + st->num_objs;
st->num_objs ++;
memcpy(temp, obj, sizeof(_cups_ps_obj_t));
return (temp);
}
Here, obj is an argument at the call of push_stack in copy_stack, and it was pointing to the st structure that is freed in realloc.
static int /* O - 0 on success, -1 on error */
copy_stack(_cups_ps_stack_t *st, /* I - Stack */
int c) /* I - Number of objects to copy */
{
int n; /* Index */
if (c < 0)
return (-1);
else if (c == 0)
return (0);
if ((n = st->num_objs - c) < 0)
return (-1);
while (c > 0)
{
if (!push_stack(st, st->objs + n))
return (-1);
n ++;
c --;
}
return (0);
}