Created attachment 20460 [details] Crash Hello! This bug was found by Crusher (developing at ISP RAS), thanks to following colleagues: Maxim Mishechkin, Vitalii Akolzin, Shamil Kurmangaleev, Denis Straghkov, Fedor Nis'kov, Ivan Gulakov. Product version: mupdf-1.18.0 Environment: 18.04 To reproduce: 1. Download file crash crash_mutool.tar.gz 2. Extract crash_mutool.tar.gz 3. Run mutool with options: clean -s -d -a -l -z ./mutool clean -s -d -a -l -z id_crash_0 out_file.pdf Program crashes with SIGABRT. Error message: warning: first object in xref is not free warning: object out of range (0 0 R); xref size 61 corrupted double-linked list [1] 55708 abort ./mutool clean -s -d -a -l -z ../../../id_crash_0 out_file.pdf GDB output: Program received signal SIGABRT, Aborted. __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51 51 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory. (gdb) bt #0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51 #1 0x00007ffff6f9a921 in __GI_abort () at abort.c:79 #2 0x00007ffff6fe3967 in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7ffff7110b0d "%s\n") at ../sysdeps/posix/libc_fatal.c:181 #3 0x00007ffff6fea9da in malloc_printerr (str=str@entry=0x7ffff710ec3a "corrupted double-linked list") at malloc.c:5342 #4 0x00007ffff6ff225f in _int_free (have_lock=0, p=<optimized out>, av=0x7ffff7345c40 <main_arena>) at malloc.c:4325 #5 __GI___libc_free (mem=<optimized out>) at malloc.c:3134 #6 0x000055555560fa14 in ?? () #7 0x0000555555671752 in ?? () #8 0x0000555555671738 in ?? () #9 0x0000555555691825 in ?? () #10 0x0000555555691923 in ?? () #11 0x000055555569222d in ?? () #12 0x00005555555d0a66 in ?? () #13 0x000055555564a28e in ?? () #14 0x00005555555be8c5 in ?? () #15 0x00007ffff6f7bbf7 in __libc_start_main (main=0x55555559e870, argc=9, argv=0x7fffffffe418, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe408) at ../csu/libc-start.c:310 #16 0x000055555559eb9a in ?? () Valgrind output: ==147614== Memcheck, a memory error detector ==147614== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==147614== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info ==147614== Command: ./mutool clean -s -d -a -l -z ../../../id_crash_0 out_file.pdf ==147614== warning: first object in xref is not free ==147614== Invalid read of size 2 ==147614== at 0x225672: ??? (in ./mutool) ==147614== by 0x245824: ??? (in ./mutool) ==147614== by 0x245922: ??? (in ./mutool) ==147614== by 0x24ABA3: ??? (in ./mutool) ==147614== by 0x23BE49: ??? (in ./mutool) ==147614== by 0x241DF3: ??? (in ./mutool) ==147614== by 0x2435AD: ??? (in ./mutool) ==147614== by 0x1FE6CE: ??? (in ./mutool) ==147614== by 0x1728C4: ??? (in ./mutool) ==147614== by 0x58E7BF6: (below main) (libc-start.c:310) ==147614== Address 0x5f4cc80 is 0 bytes inside a block of size 40 free'd ==147614== at 0x4C32D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==147614== by 0x1C3A13: ??? (in ./mutool) ==147614== by 0x24587B: ??? (in ./mutool) ==147614== by 0x245922: ??? (in ./mutool) ==147614== by 0x24ABA3: ??? (in ./mutool) ==147614== by 0x23BE49: ??? (in ./mutool) ==147614== by 0x241B3F: ??? (in ./mutool) ==147614== by 0x2435AD: ??? (in ./mutool) ==147614== by 0x1FE6CE: ??? (in ./mutool) ==147614== by 0x1728C4: ??? (in ./mutool) ==147614== by 0x58E7BF6: (below main) (libc-start.c:310) ==147614== Block was alloc'd at ==147614== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==147614== by 0x1C386B: ??? (in ./mutool) ==147614== by 0x1C38B5: ??? (in ./mutool) ==147614== by 0x221E1E: ??? (in ./mutool) ==147614== by 0x233B0D: ??? (in ./mutool) ==147614== by 0x234626: ??? (in ./mutool) ==147614== by 0x24758E: ??? (in ./mutool) ==147614== by 0x2476EC: ??? (in ./mutool) ==147614== by 0x247CD6: ??? (in ./mutool) ==147614== by 0x247FBA: ??? (in ./mutool) ==147614== by 0x248506: ??? (in ./mutool) ==147614== by 0x24DEA7: ??? (in ./mutool) ==147614== ==147614== Invalid read of size 2 ==147614== at 0x225672: ??? (in ./mutool) ==147614== by 0x245824: ??? (in ./mutool) ==147614== by 0x245922: ??? (in ./mutool) ==147614== by 0x24622C: ??? (in ./mutool) ==147614== by 0x184A65: ??? (in ./mutool) ==147614== by 0x1FE28D: ??? (in ./mutool) ==147614== by 0x1728C4: ??? (in ./mutool) ==147614== by 0x58E7BF6: (below main) (libc-start.c:310) ==147614== Address 0x5f4cc80 is 0 bytes inside a block of size 40 free'd ==147614== at 0x4C32D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==147614== by 0x1C3A13: ??? (in ./mutool) ==147614== by 0x24587B: ??? (in ./mutool) ==147614== by 0x245922: ??? (in ./mutool) ==147614== by 0x24ABA3: ??? (in ./mutool) ==147614== by 0x23BE49: ??? (in ./mutool) ==147614== by 0x241B3F: ??? (in ./mutool) ==147614== by 0x2435AD: ??? (in ./mutool) ==147614== by 0x1FE6CE: ??? (in ./mutool) ==147614== by 0x1728C4: ??? (in ./mutool) ==147614== by 0x58E7BF6: (below main) (libc-start.c:310) ==147614== Block was alloc'd at ==147614== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==147614== by 0x1C386B: ??? (in ./mutool) ==147614== by 0x1C38B5: ??? (in ./mutool) ==147614== by 0x221E1E: ??? (in ./mutool) ==147614== by 0x233B0D: ??? (in ./mutool) ==147614== by 0x234626: ??? (in ./mutool) ==147614== by 0x24758E: ??? (in ./mutool) ==147614== by 0x2476EC: ??? (in ./mutool) ==147614== by 0x247CD6: ??? (in ./mutool) ==147614== by 0x247FBA: ??? (in ./mutool) ==147614== by 0x248506: ??? (in ./mutool) ==147614== by 0x24DEA7: ??? (in ./mutool) ==147614== ==147614== ==147614== HEAP SUMMARY: ==147614== in use at exit: 0 bytes in 0 blocks ==147614== total heap usage: 8,334 allocs, 8,334 frees, 7,601,622 bytes allocated ==147614== ==147614== All heap blocks were freed -- no leaks are possible ==147614== ==147614== For counts of detected and suppressed errors, rerun with: -v ==147614== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) Analysis 1. In the “pdf_new_dict” function source/pdf/pdf-object.c: 907 obj = Memento_label (fz_malloc (ctx, sizeof (pdf_obj_dict)), "pdf_obj (dict)"); In this line, memory allocated for dictionary (data type in a pdf file). 2. Then, in the process of garbage collection, duplicate objects (various entities of the pdf format) deleted, and they renumbered. The previously created dictionary object is deleted in the pdf_drop_dict (pdf-object.c: 1702)) function. source/pdf/pdf-object.c: 1702 fz_free (ctx, obj); 3. Valgrind detected a call to the field of size 2 bytes of the dictionary object, which deleted in the function fz_drop_imp16. include/mupdf/fitz/context.h: 702 if (* refs> 0) 4. After that, the dictionary object freed again, which leads to SIGABORT because the address of the freed chunk has already freed. 5. For further exploitation, it is necessary to place data of the same size in this chunk and select a situation with the dictionary, such that this will lead to exploitation.
GDB with debug: [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". warning: first object in xref is not free warning: object out of range (0 0 R); xref size 61 corrupted double-linked list Program received signal SIGABRT, Aborted. __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51 51 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory. (gdb) bt #0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51 #1 0x00007ffff6f9a921 in __GI_abort () at abort.c:79 #2 0x00007ffff6fe3967 in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7ffff7110b0d "%s\n") at ../sysdeps/posix/libc_fatal.c:181 #3 0x00007ffff6fea9da in malloc_printerr (str=str@entry=0x7ffff710ec3a "corrupted double-linked list") at malloc.c:5342 #4 0x00007ffff6ff225f in _int_free (have_lock=0, p=<optimized out>, av=0x7ffff7345c40 <main_arena>) at malloc.c:4325 #5 __GI___libc_free (mem=<optimized out>) at malloc.c:3134 #6 0x000055555563095a in fz_free_default (opaque=0x0, ptr=0x555557e9d670) at source/fitz/memory.c:170 #7 0x000055555563088b in fz_free (ctx=0x555557e74260, p=0x555557e9d670) at source/fitz/memory.c:141 #8 0x00005555556b64d5 in pdf_drop_dict (ctx=0x555557e74260, obj=0x555557e9ea50) at source/pdf/pdf-object.c:1701 #9 0x00005555556b65a1 in pdf_drop_obj (ctx=0x555557e74260, obj=0x555557e9ea50) at source/pdf/pdf-object.c:1723 #10 0x00005555556b64ae in pdf_drop_dict (ctx=0x555557e74260, obj=0x555557e9e880) at source/pdf/pdf-object.c:1698 #11 0x00005555556b65a1 in pdf_drop_obj (ctx=0x555557e74260, obj=0x555557e9e880) at source/pdf/pdf-object.c:1723 #12 0x00005555556df241 in pdf_drop_xref_sections_imp (ctx=0x555557e74260, doc=0x555557e8c400, xref_sections=0x555557e9d930, num_xref_sections=1) at source/pdf/pdf-xref.c:47 #13 0x00005555556df3b8 in pdf_drop_xref_sections (ctx=0x555557e74260, doc=0x555557e8c400) at source/pdf/pdf-xref.c:74 #14 0x00005555556e3d62 in pdf_drop_document_imp (ctx=0x555557e74260, doc=0x555557e8c400) at source/pdf/pdf-xref.c:1562 #15 0x00005555555dc267 in fz_drop_document (ctx=0x555557e74260, doc=0x555557e8c400) at source/fitz/document.c:278 #16 0x00005555556e40ac in pdf_drop_document (ctx=0x555557e74260, doc=0x555557e8c400) at source/pdf/pdf-xref.c:1621 #17 0x00005555556837c9 in pdf_clean_file (ctx=0x555557e74260, infile=0x7fffffffe71a "../id_crash_0", outfile=0x7fffffffe728 "out_file.pdf", password=0x555555a6327e "", opts=0x7fffffffe1b0, argc=0, argv=0x7fffffffe490) at source/pdf/pdf-clean-file.c:337 #18 0x00005555555c52a1 in pdfclean_main (argc=8, argv=0x7fffffffe450) at source/tools/pdfclean.c:117 #19 0x00005555555a00a0 in main (argc=9, argv=0x7fffffffe448) at source/tools/mutool.c:130
Valgrind with --leak-check=full ==177009== Memcheck, a memory error detector ==177009== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==177009== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info ==177009== Command: build/debug/mutool clean -s -d -a -l -z ../id_crash_0 out_file.pdf ==177009== warning: first object in xref is not free ==177009== Invalid read of size 2 ==177009== at 0x265699: fz_drop_imp16 (context.h:702) ==177009== by 0x26A558: pdf_drop_obj (pdf-object.c:1718) ==177009== by 0x293240: pdf_drop_xref_sections_imp (pdf-xref.c:47) ==177009== by 0x2933B7: pdf_drop_xref_sections (pdf-xref.c:74) ==177009== by 0x294A69: pdf_replace_xref (pdf-xref.c:536) ==177009== by 0x2887E2: renumberobjs (pdf-write.c:943) ==177009== by 0x28A57C: linearize (pdf-write.c:1516) ==177009== by 0x290C5C: do_pdf_save_document (pdf-write.c:3421) ==177009== by 0x291968: pdf_save_document (pdf-write.c:3639) ==177009== by 0x2377A5: pdf_clean_file (pdf-clean-file.c:333) ==177009== by 0x1792A0: pdfclean_main (pdfclean.c:117) ==177009== by 0x15409F: main (mutool.c:130) ==177009== Address 0x5f4cc90 is 0 bytes inside a block of size 40 free'd ==177009== at 0x4C32D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==177009== by 0x1E4959: fz_free_default (memory.c:170) ==177009== by 0x1E488A: fz_free (memory.c:141) ==177009== by 0x26A4E7: pdf_drop_dict (pdf-object.c:1702) ==177009== by 0x26A5A0: pdf_drop_obj (pdf-object.c:1723) ==177009== by 0x2932D2: pdf_drop_xref_sections_imp (pdf-xref.c:57) ==177009== by 0x2933B7: pdf_drop_xref_sections (pdf-xref.c:74) ==177009== by 0x294A69: pdf_replace_xref (pdf-xref.c:536) ==177009== by 0x2887E2: renumberobjs (pdf-write.c:943) ==177009== by 0x290BC1: do_pdf_save_document (pdf-write.c:3409) ==177009== by 0x291968: pdf_save_document (pdf-write.c:3639) ==177009== by 0x2377A5: pdf_clean_file (pdf-clean-file.c:333) ==177009== Block was alloc'd at ==177009== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==177009== by 0x1E4912: fz_malloc_default (memory.c:158) ==177009== by 0x1E4438: do_scavenging_malloc (memory.c:29) ==177009== by 0x1E4593: fz_malloc (memory.c:67) ==177009== by 0x267BFF: pdf_new_dict (pdf-object.c:907) ==177009== by 0x27D15C: pdf_parse_dict (pdf-parse.c:602) ==177009== by 0x27D8C0: pdf_parse_ind_obj (pdf-parse.c:770) ==177009== by 0x296400: pdf_read_new_xref (pdf-xref.c:1014) ==177009== by 0x2968BB: pdf_read_xref (pdf-xref.c:1105) ==177009== by 0x29692C: read_xref_section (pdf-xref.c:1120) ==177009== by 0x296C11: pdf_read_xref_sections (pdf-xref.c:1189) ==177009== by 0x296DC3: pdf_load_xref (pdf-xref.c:1245) ==177009== ==177009== ==177009== HEAP SUMMARY: ==177009== in use at exit: 0 bytes in 0 blocks ==177009== total heap usage: 8,334 allocs, 8,334 frees, 7,601,638 bytes allocated ==177009== ==177009== All heap blocks were freed -- no leaks are possible ==177009== ==177009== For counts of detected and suppressed errors, rerun with: -v ==177009== ERROR SUMMARY: 2 errors from 1 contexts (suppressed: 0 from 0)
Solved in: commit cee7cefc610d42fd383b3c80c12cbc675443176a Author: Robin Watts <Robin.Watts@artifex.com> Date: Fri Jan 22 17:05:15 2021 +0000 Bug 703366: Fix double free of object during linearization. This appears to happen because we parse an illegal object from a broken file and assign it to object 0, which is defined to be free. Here, we fix the parsing code so this can't happen.
What about registration CVE for this vulnerability?
Ping