clazzes-ghostscript 9.54.0 Security Review

Resources

List of third party libraries

https://www.ghostscript.com/doc/current/thirdparty.htm

checked against code

https://github.com/ArtifexSoftware/ghostpdl/tree/ghostpdl-9.54.0

Configuration of clazzes-ghostscript

The following configure options are used for clazzes-ghostscript

./configure --prefix=/usr/clazzes-ghostscript --enable-dynamic
--disable-cups --disable-gtk --without-x

Hence, the security review does not need to cover the CUPS library or any X-Windows or GTK-releated ghostscript issues.

Applicable Third Party Libraries

Library Name

Version

Function

License

URL

Library Name

Version

Function

License

URL

eXpat

2.2.9

XML parsing for XPS interpreter

MIT/eXpat License

http://expat.sourceforge.net/

FreeType

2.10.4

Font scaling and rendering for Ghostscript

FreeType License
(BSD-style license with a credit clause)

http://www.freetype.org/

jbig2dec

0.19

JBIG2 decoding for the PDF interpreter

Licensed with Ghostscript/GhostPDL
(copyright owned by Artifex)

http://www.ghostscript.com/

libjpeg

9c
with patches

JPEG/DCT decoding/encoding

"Free"
Can be used in commercial applications without royalty, with acknowledgement.

http://www.ijg.org/

LittleCMS 2 mt
(lcms2mt – thread save fork of lcms2)

2.12

ICC profile based color conversion and management

MIT LICENSE

http://www.ghostscript.com/

libpng

1.6.37

PNG image encoding/decoding.

libpng license
classified as "a permissive free software license"

http://www.libpng.org/

OpenJPEG

2.4.0

JPEG2000 image decoding for the PDF interpreter

BSD-style

http://www.openjpeg.org/

libtiff

4.2.0

TIFF image encoding/decoding

BSD-style

http://www.remotesensing.org/libtiff/

zlib

1.2.11

(De)Flate compression

zlib License
classified as "a permissive free software license"

http://www.zlib.net/

Review of CVEs

CVEs of ghostscript-9.54.0

Query:

https://nvd.nist.gov/vuln/search/results?form_type=Basic&results_type=overview&query=ghostscript&search_type=last3years

As of 2021-11-16 no major CVEs are open against the core ghostscript project apart from https://www.ghostscript.com/blog/CVE-2021-3781.html published on the ghostscript homepage itself.

The patch https://git.ghostscript.com/?p=ghostpdl.git;a=commitdiff_plain;h=a9bd3dec9fde for CVE-2021-3781 applies to ghostscript-9.54.0 sources and has been intergrated into clazzes-ghostscript.

A long list of vulnerabilites (CVE-2020-16287 up to CVE-2020-16310 and CVE-2020-17538) has been fixed for ghostscript-9.51 after a thorough security review.

 

CVEs of libexpat 2.2.9

https://nvd.nist.gov/vuln/search/results?form_type=Basic&results_type=overview&query=expat&search_type=last3months

No known CVEs as of 2021-11-16. CVE-2021-40439 is specific to OpenOffice and has no impact on ghostscript.

CVEs of freetype 2.10.4

https://nvd.nist.gov/vuln/search/results?form_type=Basic&results_type=overview&query=freetype&search_type=last3months

freetype-2.10.4is subject to no vulnerabilities as of 2021-11-16

The upgraded to freetype-2.10.4 has been conducted between ghostscript.9.53.3 and ghostscript-9.54.0

CVEs of jbig2dec 0.19

https://nvd.nist.gov/vuln/search/results?form_type=Basic&results_type=overview&query=jbig2dec&search_type=last3months

jbig2dec-0.19 is subject to no vulnerabilities as 2021-11-16

CVEs of libjpeg-9c

https://nvd.nist.gov/vuln/search/results?form_type=Basic&results_type=overview&query=libjpeg&search_type=last3months

libjpeg-9c is vulnerable to

https://nvd.nist.gov/vuln/detail/CVE-2020-14152

https://nvd.nist.gov/vuln/detail/CVE-2020-14153

Hence, we upgraded to libjpeg-9d as of svn rev. 72, which has no vulvnerabilities as of 2021-11-16

CVE-2021-39514 through CVE-2021-39520 are address a different library (https://github.com/thorfdbg/libjpeg), which is also called libjpeg and is implemented in C++ rather than plain C.

CVEs of libpng-1.6.37

https://nvd.nist.gov/vuln/search/results?form_type=Basic&results_type=overview&query=libpng&search_type=last3years

No known CVEs as of 2020-12-27.

CVEs of openjpeg-2.4.0

https://nvd.nist.gov/vuln/search/results?form_type=Basic&results_type=overview&query=openjpeg&search_type=last3months

The vulnerability

CVE-2021-29338

only affects openjpeg cmdline tools, which are not included in ghostscript, because ghostscript actually uses the openjpeg library.

openjpeg-2.4.0 resolves several vulnerabilities compared to openjpeg-2.3.1

CVEs fo libtiff-4.2.0

https://nvd.nist.gov/vuln/search/results?form_type=Basic&results_type=overview&query=libtiff&search_type=last3months

All CVEs are reported against libtiff-4.0.x and a review of git commits revealed, that libtiff-4.2.0 is indeed incorporating all fixes for the CVEs listed above.

CVEs of zlib 1.2.11

https://nvd.nist.gov/vuln/search/results?form_type=Basic&results_type=overview&query=zlib&search_type=last3months

This list contains only CVEs of third parties with correctly applying the awkward zlib API with buffer over- and/or underruns. zlib itself is not subject to any CVE, which appeared during the last 3 years.

valgrind Runs

These valgrind runs are based on an example from our customers, which crashed ghostscript-9.25 when rendering to the pngalpha output device. The example involves fonts, image masks and is otherwise not very complex.

The test runs have been executed on a centos8 machine with recent centos 8.4 updates as of 2021-11-16.

valgrind clazzes-ghostscript-9.54.0-1 pngalpha

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 # valgrind /usr/clazzes-ghostscript/bin/gs -sDEVICE=pngalpha -sOutputFile=tmp.png -dSAFER -dBATCH -dNOPAUSE -dUseCropBox -dFirstPage=1 -dLastPage=1 -r100.0 -f tmp.pdf ==1701570== Memcheck, a memory error detector ==1701570== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==1701570== Using Valgrind-3.16.0 and LibVEX; rerun with -h for copyright info ==1701570== Command: /usr/clazzes-ghostscript/bin/gs -sDEVICE=pngalpha -sOutputFile=tmp.png -dSAFER -dBATCH -dNOPAUSE -dUseCropBox -dFirstPage=1 -dLastPage=1 -r100.0 -f tmp.pdf ==1701570== GPL Ghostscript 9.54.0 (2021-03-30) Copyright (C) 2021 Artifex Software, Inc. All rights reserved. This software is supplied under the GNU AGPLv3 and comes with NO WARRANTY: see the file COPYING for details. Processing pages 1 through 1. Page 1 ==1701570== Syscall param pwrite64(buf) points to uninitialised byte(s) ==1701570== at 0x53DA278: pwrite (in /usr/lib64/libpthread-2.28.so) ==1701570== by 0x45D2E4: gp_pwrite_impl (in /usr/clazzes-ghostscript/bin/gs) ==1701570== by 0x565697: clist_fwrite_chars (in /usr/clazzes-ghostscript/bin/gs) ==1701570== by 0x54F89B: cmd_write_pseudo_band (in /usr/clazzes-ghostscript/bin/gs) ==1701570== by 0x53C748: clist_icc_writetable (in /usr/clazzes-ghostscript/bin/gs) ==1701570== by 0x53CB6B: clist_end_page (in /usr/clazzes-ghostscript/bin/gs) ==1701570== by 0x5492BF: clist_close_writer_and_init_reader (in /usr/clazzes-ghostscript/bin/gs) ==1701570== by 0x549C02: clist_get_bits_rectangle (in /usr/clazzes-ghostscript/bin/gs) ==1701570== by 0x87FD3A: gx_default_get_bits (in /usr/clazzes-ghostscript/bin/gs) ==1701570== by 0x530A63: gx_downscaler_getbits (in /usr/clazzes-ghostscript/bin/gs) ==1701570== by 0x77C5A1: do_png_print_page (in /usr/clazzes-ghostscript/bin/gs) ==1701570== by 0x5286AC: gdev_prn_output_page_aux (in /usr/clazzes-ghostscript/bin/gs) ==1701570== Address 0x60bbda0 is 2,768 bytes inside a block of size 20,048 alloc'd ==1701570== at 0x4C34F0B: malloc (vg_replace_malloc.c:307) ==1701570== by 0x7A37B7: gs_heap_alloc_bytes (in /usr/clazzes-ghostscript/bin/gs) ==1701570== by 0x780524: alloc_acquire_clump (in /usr/clazzes-ghostscript/bin/gs) ==1701570== by 0x7813E1: alloc_obj.isra.4 (in /usr/clazzes-ghostscript/bin/gs) ==1701570== by 0x77C9AE: gdevpng_malloc (in /usr/clazzes-ghostscript/bin/gs) ==1701570== by 0x4D55D3: png_malloc_warn (in /usr/clazzes-ghostscript/bin/gs) ==1701570== by 0x4D7336: png_set_iCCP (in /usr/clazzes-ghostscript/bin/gs) ==1701570== by 0x77C867: do_png_print_page (in /usr/clazzes-ghostscript/bin/gs) ==1701570== by 0x5286AC: gdev_prn_output_page_aux (in /usr/clazzes-ghostscript/bin/gs) ==1701570== by 0x538D95: default_subclass_output_page (in /usr/clazzes-ghostscript/bin/gs) ==1701570== by 0x52B915: flp_output_page (in /usr/clazzes-ghostscript/bin/gs) ==1701570== by 0x88255D: gx_forward_output_page (in /usr/clazzes-ghostscript/bin/gs) ==1701570== ==1701570== ==1701570== HEAP SUMMARY: ==1701570== in use at exit: 0 bytes in 0 blocks ==1701570== total heap usage: 7,238 allocs, 7,238 frees, 113,288,380 bytes allocated ==1701570== ==1701570== All heap blocks were freed -- no leaks are possible ==1701570== ==1701570== Use --track-origins=yes to see where uninitialised values come from ==1701570== For lists of detected and suppressed errors, rerun with: -s ==1701570== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

The reported writing of uninitialized memory seems to be immanent to the png output writer, this is a frequent warning for compressed output wrriting.

valgrind ghostscript-9.27-1.el8 pngalpha

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 # valgrind /usr/bin/gs -sDEVICE=pngalpha -sOutputFile=tmp.png -dSAFER -dBATCH -dNOPAUSE -dUseCropBox -dFirstPage=1 -dLastPage=1 -r100.0 -f tmp.pdf ==1701568== Memcheck, a memory error detector ==1701568== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==1701568== Using Valgrind-3.16.0 and LibVEX; rerun with -h for copyright info ==1701568== Command: /usr/bin/gs -sDEVICE=pngalpha -sOutputFile=tmp.png -dSAFER -dBATCH -dNOPAUSE -dUseCropBox -dFirstPage=1 -dLastPage=1 -r100.0 -f tmp.pdf ==1701568== GPL Ghostscript 9.27 (2019-04-04) Copyright (C) 2018 Artifex Software, Inc. All rights reserved. This software is supplied under the GNU AGPLv3 and comes with NO WARRANTY: see the file COPYING for details. Processing pages 1 through 1. Page 1 ==1701568== Syscall param pwrite64(buf) points to uninitialised byte(s) ==1701568== at 0x60C3977: pwrite (in /usr/lib64/libc-2.28.so) ==1701568== by 0x4F5A706: gp_fpwrite (in /usr/lib64/libgs.so.9.27) ==1701568== by 0x5040C4C: ??? (in /usr/lib64/libgs.so.9.27) ==1701568== by 0x502BE1F: cmd_write_pseudo_band (in /usr/lib64/libgs.so.9.27) ==1701568== by 0x5018DE2: clist_icc_writetable (in /usr/lib64/libgs.so.9.27) ==1701568== by 0x501923F: clist_end_page (in /usr/lib64/libgs.so.9.27) ==1701568== by 0x50253D7: clist_close_writer_and_init_reader (in /usr/lib64/libgs.so.9.27) ==1701568== by 0x5025E02: clist_get_bits_rectangle (in /usr/lib64/libgs.so.9.27) ==1701568== by 0x503ECF9: ??? (in /usr/lib64/libgs.so.9.27) ==1701568== by 0x5200152: gx_default_get_bits (in /usr/lib64/libgs.so.9.27) ==1701568== by 0x500CE7E: gx_downscaler_getbits (in /usr/lib64/libgs.so.9.27) ==1701568== by 0x51712D9: ??? (in /usr/lib64/libgs.so.9.27) ==1701568== Address 0xf040a88 is 9,224 bytes inside a block of size 20,048 alloc'd ==1701568== at 0x4C34F0B: malloc (vg_replace_malloc.c:307) ==1701568== by 0x5196DC3: ??? (in /usr/lib64/libgs.so.9.27) ==1701568== by 0x51735F4: ??? (in /usr/lib64/libgs.so.9.27) ==1701568== by 0x517450E: ??? (in /usr/lib64/libgs.so.9.27) ==1701568== by 0x52833E7: gs_alloc_ref_array (in /usr/lib64/libgs.so.9.27) ==1701568== by 0x524A7CD: ??? (in /usr/lib64/libgs.so.9.27) ==1701568== by 0x524AB54: dict_unpack (in /usr/lib64/libgs.so.9.27) ==1701568== by 0x524BBA5: dict_put (in /usr/lib64/libgs.so.9.27) ==1701568== by 0x5264251: ??? (in /usr/lib64/libgs.so.9.27) ==1701568== by 0x5250597: gs_interpret (in /usr/lib64/libgs.so.9.27) ==1701568== by 0x5243ADB: ??? (in /usr/lib64/libgs.so.9.27) ==1701568== by 0x5243FFF: gs_main_init2aux (in /usr/lib64/libgs.so.9.27) ==1701568== ==1701568== ==1701568== HEAP SUMMARY: ==1701568== in use at exit: 0 bytes in 0 blocks ==1701568== total heap usage: 10,980 allocs, 10,980 frees, 129,841,737 bytes allocated ==1701568== ==1701568== All heap blocks were freed -- no leaks are possible ==1701568== ==1701568== Use --track-origins=yes to see where uninitialised values come from ==1701568== For lists of detected and suppressed errors, rerun with: -s ==1701568== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

The original crash from gs-9.25 as of RHEL-8.1 crash has ben fixed in RHEL-8.4

valgrind clazzes-ghostscript-9.54.0-1 png16m

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 # valgrind /usr/clazzes-ghostscript/bin/gs -sDEVICE=png16m -sOutputFile=tmp.png -dSAFER -dBATCH -dNOPAUSE -dUseCropBox -dFirstPage=1 -dLastPage=1 -r100.0 -f tmp.pdf ==1701565== Memcheck, a memory error detector ==1701565== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==1701565== Using Valgrind-3.16.0 and LibVEX; rerun with -h for copyright info ==1701565== Command: /usr/clazzes-ghostscript/bin/gs -sDEVICE=png16m -sOutputFile=tmp.png -dSAFER -dBATCH -dNOPAUSE -dUseCropBox -dFirstPage=1 -dLastPage=1 -r100.0 -f tmp.pdf ==1701565== GPL Ghostscript 9.54.0 (2021-03-30) Copyright (C) 2021 Artifex Software, Inc. All rights reserved. This software is supplied under the GNU AGPLv3 and comes with NO WARRANTY: see the file COPYING for details. Processing pages 1 through 1. Page 1 ==1701565== Syscall param pwrite64(buf) points to uninitialised byte(s) ==1701565== at 0x53DA278: pwrite (in /usr/lib64/libpthread-2.28.so) ==1701565== by 0x45D2E4: gp_pwrite_impl (in /usr/clazzes-ghostscript/bin/gs) ==1701565== by 0x565697: clist_fwrite_chars (in /usr/clazzes-ghostscript/bin/gs) ==1701565== by 0x54F89B: cmd_write_pseudo_band (in /usr/clazzes-ghostscript/bin/gs) ==1701565== by 0x53C748: clist_icc_writetable (in /usr/clazzes-ghostscript/bin/gs) ==1701565== by 0x53CB6B: clist_end_page (in /usr/clazzes-ghostscript/bin/gs) ==1701565== by 0x5492BF: clist_close_writer_and_init_reader (in /usr/clazzes-ghostscript/bin/gs) ==1701565== by 0x549C02: clist_get_bits_rectangle (in /usr/clazzes-ghostscript/bin/gs) ==1701565== by 0x87FD3A: gx_default_get_bits (in /usr/clazzes-ghostscript/bin/gs) ==1701565== by 0x530A63: gx_downscaler_getbits (in /usr/clazzes-ghostscript/bin/gs) ==1701565== by 0x77C5A1: do_png_print_page (in /usr/clazzes-ghostscript/bin/gs) ==1701565== by 0x5286AC: gdev_prn_output_page_aux (in /usr/clazzes-ghostscript/bin/gs) ==1701565== Address 0x8122190 is 16,656 bytes inside a block of size 20,048 alloc'd ==1701565== at 0x4C34F0B: malloc (vg_replace_malloc.c:307) ==1701565== by 0x7A37B7: gs_heap_alloc_bytes (in /usr/clazzes-ghostscript/bin/gs) ==1701565== by 0x780524: alloc_acquire_clump (in /usr/clazzes-ghostscript/bin/gs) ==1701565== by 0x7813E1: alloc_obj.isra.4 (in /usr/clazzes-ghostscript/bin/gs) ==1701565== by 0x8FDA63: gs_alloc_ref_array (in /usr/clazzes-ghostscript/bin/gs) ==1701565== by 0x8C7BCD: dict_create_unpacked_keys.isra.0 (in /usr/clazzes-ghostscript/bin/gs) ==1701565== by 0x8C7F05: dict_unpack (in /usr/clazzes-ghostscript/bin/gs) ==1701565== by 0x8C8EB1: dict_put (in /usr/clazzes-ghostscript/bin/gs) ==1701565== by 0x8E0651: zput (in /usr/clazzes-ghostscript/bin/gs) ==1701565== by 0x8CD598: gs_interpret (in /usr/clazzes-ghostscript/bin/gs) ==1701565== by 0x8C0FB8: gs_main_run_string_end (in /usr/clazzes-ghostscript/bin/gs) ==1701565== by 0x8C102F: gs_main_run_string_with_length (in /usr/clazzes-ghostscript/bin/gs) ==1701565== ==1701565== ==1701565== HEAP SUMMARY: ==1701565== in use at exit: 0 bytes in 0 blocks ==1701565== total heap usage: 6,391 allocs, 6,391 frees, 101,989,676 bytes allocated ==1701565== ==1701565== All heap blocks were freed -- no leaks are possible ==1701565== ==1701565== Use --track-origins=yes to see where uninitialised values come from ==1701565== For lists of detected and suppressed errors, rerun with: -s ==1701565== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

This works as expected.

valgrind ghostscript-9.27-1.el8 png16m

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 # valgrind /usr/bin/gs -sDEVICE=png16m -sOutputFile=tmp.png -dSAFER -dBATCH -dNOPAUSE -dUseCropBox -dFirstPage=1 -dLastPage=1 -r100.0 -f tmp.pdf ==1701516== Memcheck, a memory error detector ==1701516== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==1701516== Using Valgrind-3.16.0 and LibVEX; rerun with -h for copyright info ==1701516== Command: /usr/bin/gs -sDEVICE=png16m -sOutputFile=tmp.png -dSAFER -dBATCH -dNOPAUSE -dUseCropBox -dFirstPage=1 -dLastPage=1 -r100.0 -f tmp.pdf ==1701516== GPL Ghostscript 9.27 (2019-04-04) Copyright (C) 2018 Artifex Software, Inc. All rights reserved. This software is supplied under the GNU AGPLv3 and comes with NO WARRANTY: see the file COPYING for details. Processing pages 1 through 1. Page 1 ==1701516== Syscall param pwrite64(buf) points to uninitialised byte(s) ==1701516== at 0x60C3977: pwrite (in /usr/lib64/libc-2.28.so) ==1701516== by 0x4F5A706: gp_fpwrite (in /usr/lib64/libgs.so.9.27) ==1701516== by 0x5040C4C: ??? (in /usr/lib64/libgs.so.9.27) ==1701516== by 0x502BE1F: cmd_write_pseudo_band (in /usr/lib64/libgs.so.9.27) ==1701516== by 0x5018DE2: clist_icc_writetable (in /usr/lib64/libgs.so.9.27) ==1701516== by 0x501923F: clist_end_page (in /usr/lib64/libgs.so.9.27) ==1701516== by 0x50253D7: clist_close_writer_and_init_reader (in /usr/lib64/libgs.so.9.27) ==1701516== by 0x5025E02: clist_get_bits_rectangle (in /usr/lib64/libgs.so.9.27) ==1701516== by 0x503ECF9: ??? (in /usr/lib64/libgs.so.9.27) ==1701516== by 0x5200152: gx_default_get_bits (in /usr/lib64/libgs.so.9.27) ==1701516== by 0x500CE7E: gx_downscaler_getbits (in /usr/lib64/libgs.so.9.27) ==1701516== by 0x51712D9: ??? (in /usr/lib64/libgs.so.9.27) ==1701516== Address 0xf0405f8 is 8,056 bytes inside a block of size 20,048 alloc'd ==1701516== at 0x4C34F0B: malloc (vg_replace_malloc.c:307) ==1701516== by 0x5196DC3: ??? (in /usr/lib64/libgs.so.9.27) ==1701516== by 0x51735F4: ??? (in /usr/lib64/libgs.so.9.27) ==1701516== by 0x517450E: ??? (in /usr/lib64/libgs.so.9.27) ==1701516== by 0x52833E7: gs_alloc_ref_array (in /usr/lib64/libgs.so.9.27) ==1701516== by 0x524A7CD: ??? (in /usr/lib64/libgs.so.9.27) ==1701516== by 0x524AB54: dict_unpack (in /usr/lib64/libgs.so.9.27) ==1701516== by 0x524BBA5: dict_put (in /usr/lib64/libgs.so.9.27) ==1701516== by 0x5264251: ??? (in /usr/lib64/libgs.so.9.27) ==1701516== by 0x5250597: gs_interpret (in /usr/lib64/libgs.so.9.27) ==1701516== by 0x5243ADB: ??? (in /usr/lib64/libgs.so.9.27) ==1701516== by 0x5243FFF: gs_main_init2aux (in /usr/lib64/libgs.so.9.27) ==1701516== ==1701516== ==1701516== HEAP SUMMARY: ==1701516== in use at exit: 0 bytes in 0 blocks ==1701516== total heap usage: 6,480 allocs, 6,480 frees, 97,039,548 bytes allocated ==1701516== ==1701516== All heap blocks were freed -- no leaks are possible ==1701516== ==1701516== Use --track-origins=yes to see where uninitialised values come from ==1701516== For lists of detected and suppressed errors, rerun with: -s ==1701516== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

This shows, that the crash we observed is related to the pngalpha output device.