The following CVEs are fixed with this release: CVE-2018-15908, CVE-2018-15909, CVE-2018-15910, CVE-2018-15911, CVE-2018-16509, CVE-2018-16510, CVE-2018-16511, CVE-2018-16513, CVE-2018-16539, CVE-2018-16540, CVE-2018-16541, CVE-2018-16542, CVE-2018-16543. * gnu/packages/patches/ghostscript-CVE-2018-10194.patch: Delete file. * gnu/packages/patches/ghostscript-CVE-2018-16509.patch, gnu/packages/patches/ghostscript-bug-699708.patch: New files. * gnu/local.mk (dist_patch_DATA): Adjust accordingly. * gnu/packages/ghostscript.scm (ghostscript/fixed): Update to 9.24. [source](patches): Remove 'ghostscript-CVE-2018-10194.patch' and 'ghostscript-runpath.patch'. Add 'ghostscript-CVE-2018-16509.patch' and 'ghostscript-bug-699708.patch'. [arguments]: Add LDFLAGS to #:configure-flags, and a phase to create output directory.
		
			
				
	
	
		
			193 lines
		
	
	
	
		
			7.3 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			193 lines
		
	
	
	
		
			7.3 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
Ghostscript 9.24 was released with an incomplete fix for CVE-2018-16509:
 | 
						|
https://nvd.nist.gov/vuln/detail/CVE-2018-16509
 | 
						|
https://bugs.chromium.org/p/project-zero/issues/detail?id=1640#c19
 | 
						|
https://bugs.ghostscript.com/show_bug.cgi?id=699718
 | 
						|
 | 
						|
The reproducers no longer work after applying these commits:
 | 
						|
 | 
						|
https://git.ghostscript.com/?p=ghostpdl.git;a=commitdiff;h=5812b1b78fc4d36fdc293b7859de69241140d590
 | 
						|
https://git.ghostscript.com/?p=ghostpdl.git;a=commitdiff;h=e914f1da46e33decc534486598dc3eadf69e6efb
 | 
						|
https://git.ghostscript.com/?p=ghostpdl.git;a=commitdiff;h=3e5d316b72e3965b7968bb1d96baa137cd063ac6
 | 
						|
https://git.ghostscript.com/?p=ghostpdl.git;a=commitdiff;h=643b24dbd002fb9c131313253c307cf3951b3d47
 | 
						|
 | 
						|
This patch is a "squashed" version of those.
 | 
						|
 | 
						|
diff --git a/Resource/Init/gs_setpd.ps b/Resource/Init/gs_setpd.ps
 | 
						|
index bba3c8c0e..8fa7c51df 100644
 | 
						|
--- a/Resource/Init/gs_setpd.ps
 | 
						|
+++ b/Resource/Init/gs_setpd.ps
 | 
						|
@@ -95,27 +95,41 @@ level2dict begin
 | 
						|
  {	% Since setpagedevice doesn't create new device objects,
 | 
						|
         % we must (carefully) reinstall the old parameters in
 | 
						|
         % the same device.
 | 
						|
-   .currentpagedevice pop //null currentdevice //null .trysetparams
 | 
						|
+   .currentpagedevice pop //null currentdevice //null
 | 
						|
+   { .trysetparams } .internalstopped
 | 
						|
+   {
 | 
						|
+     //null
 | 
						|
+   } if
 | 
						|
    dup type /booleantype eq
 | 
						|
     { pop pop }
 | 
						|
-    {		% This should never happen!
 | 
						|
+    {
 | 
						|
       SETPDDEBUG { (Error in .trysetparams!) = pstack flush } if
 | 
						|
-      cleartomark pop pop pop
 | 
						|
+      {cleartomark pop pop pop} .internalstopped pop
 | 
						|
+      % if resetting the entire device state failed, at least put back the
 | 
						|
+      % security related key
 | 
						|
+      currentdevice //null //false mark /.LockSafetyParams
 | 
						|
+      currentpagedevice /.LockSafetyParams .knownget not
 | 
						|
+      {systemdict /SAFER .knownget not {//false} } if
 | 
						|
+      .putdeviceparamsonly
 | 
						|
       /.installpagedevice cvx /rangecheck signalerror
 | 
						|
     }
 | 
						|
    ifelse pop pop
 | 
						|
         % A careful reading of the Red Book reveals that an erasepage
 | 
						|
         % should occur, but *not* an initgraphics.
 | 
						|
    erasepage .beginpage
 | 
						|
- } bind def
 | 
						|
+ } bind executeonly def
 | 
						|
 
 | 
						|
 /.uninstallpagedevice
 | 
						|
- { 2 .endpage { .currentnumcopies //false .outputpage } if
 | 
						|
+ {
 | 
						|
+   {2 .endpage { .currentnumcopies //false .outputpage } if} .internalstopped pop
 | 
						|
    nulldevice
 | 
						|
  } bind def
 | 
						|
 
 | 
						|
 (%grestorepagedevice) cvn
 | 
						|
- { .uninstallpagedevice grestore .installpagedevice
 | 
						|
+ {
 | 
						|
+ .uninstallpagedevice
 | 
						|
+ grestore
 | 
						|
+ .installpagedevice
 | 
						|
  } bind def
 | 
						|
 
 | 
						|
 (%grestoreallpagedevice) cvn
 | 
						|
diff --git a/psi/zdevice2.c b/psi/zdevice2.c
 | 
						|
index 0c7080d57..159a0c0d9 100644
 | 
						|
--- a/psi/zdevice2.c
 | 
						|
+++ b/psi/zdevice2.c
 | 
						|
@@ -251,8 +251,8 @@ z2currentgstate(i_ctx_t *i_ctx_p)
 | 
						|
 /* ------ Wrappers for operators that reset the graphics state. ------ */
 | 
						|
 
 | 
						|
 /* Check whether we need to call out to restore the page device. */
 | 
						|
-static bool
 | 
						|
-restore_page_device(const gs_gstate * pgs_old, const gs_gstate * pgs_new)
 | 
						|
+static int
 | 
						|
+restore_page_device(i_ctx_t *i_ctx_p, const gs_gstate * pgs_old, const gs_gstate * pgs_new)
 | 
						|
 {
 | 
						|
     gx_device *dev_old = gs_currentdevice(pgs_old);
 | 
						|
     gx_device *dev_new;
 | 
						|
@@ -260,9 +260,10 @@ restore_page_device(const gs_gstate * pgs_old, const gs_gstate * pgs_new)
 | 
						|
     gx_device *dev_t2;
 | 
						|
     bool samepagedevice = obj_eq(dev_old->memory, &gs_int_gstate(pgs_old)->pagedevice,
 | 
						|
         &gs_int_gstate(pgs_new)->pagedevice);
 | 
						|
+    bool LockSafetyParams = dev_old->LockSafetyParams;
 | 
						|
 
 | 
						|
     if ((dev_t1 = (*dev_proc(dev_old, get_page_device)) (dev_old)) == 0)
 | 
						|
-        return false;
 | 
						|
+        return 0;
 | 
						|
     /* If we are going to putdeviceparams in a callout, we need to */
 | 
						|
     /* unlock temporarily.  The device will be re-locked as needed */
 | 
						|
     /* by putdeviceparams from the pgs_old->pagedevice dict state. */
 | 
						|
@@ -271,23 +272,51 @@ restore_page_device(const gs_gstate * pgs_old, const gs_gstate * pgs_new)
 | 
						|
     dev_new = gs_currentdevice(pgs_new);
 | 
						|
     if (dev_old != dev_new) {
 | 
						|
         if ((dev_t2 = (*dev_proc(dev_new, get_page_device)) (dev_new)) == 0)
 | 
						|
-            return false;
 | 
						|
-        if (dev_t1 != dev_t2)
 | 
						|
-            return true;
 | 
						|
+            samepagedevice = true;
 | 
						|
+        else if (dev_t1 != dev_t2)
 | 
						|
+            samepagedevice = false;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    if (LockSafetyParams && !samepagedevice) {
 | 
						|
+        const int required_ops = 512;
 | 
						|
+        const int required_es = 32;
 | 
						|
+
 | 
						|
+        /* The %grestorepagedevice must complete: the biggest danger
 | 
						|
+           is operand stack overflow. As we use get/putdeviceparams
 | 
						|
+           that means pushing all the device params onto the stack,
 | 
						|
+           pdfwrite having by far the largest number of parameters
 | 
						|
+           at (currently) 212 key/value pairs - thus needing (currently)
 | 
						|
+           424 entries on the op stack. Allowing for working stack
 | 
						|
+           space, and safety margin.....
 | 
						|
+         */
 | 
						|
+        if (required_ops + ref_stack_count(&o_stack) >= ref_stack_max_count(&o_stack)) {
 | 
						|
+           gs_currentdevice(pgs_old)->LockSafetyParams = LockSafetyParams;
 | 
						|
+           return_error(gs_error_stackoverflow);
 | 
						|
+        }
 | 
						|
+        /* We also want enough exec stack space - 32 is an overestimate of
 | 
						|
+           what we need to complete the Postscript call out.
 | 
						|
+         */
 | 
						|
+        if (required_es + ref_stack_count(&e_stack) >= ref_stack_max_count(&e_stack)) {
 | 
						|
+           gs_currentdevice(pgs_old)->LockSafetyParams = LockSafetyParams;
 | 
						|
+           return_error(gs_error_execstackoverflow);
 | 
						|
+        }
 | 
						|
     }
 | 
						|
     /*
 | 
						|
      * The current implementation of setpagedevice just sets new
 | 
						|
      * parameters in the same device object, so we have to check
 | 
						|
      * whether the page device dictionaries are the same.
 | 
						|
      */
 | 
						|
-    return !samepagedevice;
 | 
						|
+    return samepagedevice ? 0 : 1;
 | 
						|
 }
 | 
						|
 
 | 
						|
 /* - grestore - */
 | 
						|
 static int
 | 
						|
 z2grestore(i_ctx_t *i_ctx_p)
 | 
						|
 {
 | 
						|
-    if (!restore_page_device(igs, gs_gstate_saved(igs)))
 | 
						|
+    int code = restore_page_device(i_ctx_p, igs, gs_gstate_saved(igs));
 | 
						|
+    if (code < 0) return code;
 | 
						|
+
 | 
						|
+    if (code == 0)
 | 
						|
         return gs_grestore(igs);
 | 
						|
     return push_callout(i_ctx_p, "%grestorepagedevice");
 | 
						|
 }
 | 
						|
@@ -297,7 +326,9 @@ static int
 | 
						|
 z2grestoreall(i_ctx_t *i_ctx_p)
 | 
						|
 {
 | 
						|
     for (;;) {
 | 
						|
-        if (!restore_page_device(igs, gs_gstate_saved(igs))) {
 | 
						|
+        int code = restore_page_device(i_ctx_p, igs, gs_gstate_saved(igs));
 | 
						|
+        if (code < 0) return code;
 | 
						|
+        if (code == 0) {
 | 
						|
             bool done = !gs_gstate_saved(gs_gstate_saved(igs));
 | 
						|
 
 | 
						|
             gs_grestore(igs);
 | 
						|
@@ -328,11 +359,15 @@ z2restore(i_ctx_t *i_ctx_p)
 | 
						|
     if (code < 0) return code;
 | 
						|
 
 | 
						|
     while (gs_gstate_saved(gs_gstate_saved(igs))) {
 | 
						|
-        if (restore_page_device(igs, gs_gstate_saved(igs)))
 | 
						|
+        code = restore_page_device(i_ctx_p, igs, gs_gstate_saved(igs));
 | 
						|
+        if (code < 0) return code;
 | 
						|
+        if (code > 0)
 | 
						|
             return push_callout(i_ctx_p, "%restore1pagedevice");
 | 
						|
         gs_grestore(igs);
 | 
						|
     }
 | 
						|
-    if (restore_page_device(igs, gs_gstate_saved(igs)))
 | 
						|
+    code = restore_page_device(i_ctx_p, igs, gs_gstate_saved(igs));
 | 
						|
+    if (code < 0) return code;
 | 
						|
+    if (code > 0)
 | 
						|
         return push_callout(i_ctx_p, "%restorepagedevice");
 | 
						|
 
 | 
						|
     code = dorestore(i_ctx_p, asave);
 | 
						|
@@ -355,9 +390,12 @@ static int
 | 
						|
 z2setgstate(i_ctx_t *i_ctx_p)
 | 
						|
 {
 | 
						|
     os_ptr op = osp;
 | 
						|
+    int code;
 | 
						|
 
 | 
						|
     check_stype(*op, st_igstate_obj);
 | 
						|
-    if (!restore_page_device(igs, igstate_ptr(op)))
 | 
						|
+    code = restore_page_device(i_ctx_p, igs, igstate_ptr(op));
 | 
						|
+    if (code < 0) return code;
 | 
						|
+    if (code == 0)
 | 
						|
         return zsetgstate(i_ctx_p);
 | 
						|
     return push_callout(i_ctx_p, "%setgstatepagedevice");
 | 
						|
 }
 |