Blame SOURCES/ghostscript-cve-2018-17183.patch

09061c
From: Chris Liddell <chris.liddell@artifex.com>
09061c
Date: Thu, 6 Sep 2018 08:16:22 +0000 (+0100)
09061c
Subject: Bug 699708 (part 1): 'Hide' non-replaceable error handlers for SAFER
09061c
09061c
Bug 699708 (part 1): 'Hide' non-replaceable error handlers for SAFER
09061c
09061c
We already had a 'private' dictionary for non-standard errors: gserrordict.
09061c
09061c
This now includes all the default error handlers, the dictionary is made
09061c
noaccess and all the prodedures are bound and executeonly.
09061c
09061c
When running with -dSAFER, in the event of a Postscript error, instead of
09061c
pulling the handler from errordict, we'll pull it from gserrordict - thus
09061c
malicious input cannot trigger problems by the use of custom error handlers.
09061c
09061c
errordict remains open and writeable, so files such as the Quality Logic tests
09061c
that install their own handlers will still 'work', with the exception that the
09061c
custom error handlers will not be called.
09061c
09061c
This is a 'first pass', 'sledgehammer' approach: a nice addition would to allow
09061c
an integrator to specify a list of errors that are not to be replaced (for
09061c
example, embedded applications would probably want to ensure that VMerror is
09061c
always handled as they intend).
09061c
09061c
https://git.ghostscript.com/?p=ghostpdl.git;a=commit;h=fb713b3818b52d8a6cf62c951eba2e1795ff9624
09061c
09061c
From: Chris Liddell <chris.liddell@artifex.com>
09061c
Date: Thu, 4 Oct 2018 09:42:13 +0000 (+0100)
09061c
Subject: Bug 699832: add control over hiding error handlers.
09061c
09061c
Bug 699832: add control over hiding error handlers.
09061c
09061c
With a previous commit changing error handling in SAFER so the handler gets
09061c
passed a name object (rather than executable object), it is less critical to
09061c
hide the error handlers.
09061c
09061c
This introduces a -dSAFERERRORS option to force only use of the default error
09061c
handlers.
09061c
09061c
It also adds a .setsafererrors Postscript call, meaning a caller, without
09061c
-dSAFERERRORS, can create their own default error handlers (in errordict, as
09061c
normal), and then call .setsafererrors meaning their own handlers are always
09061c
called.
09061c
09061c
With -dSAFERERRORS or after a call to .setsafererrors, .setsafererrors is
09061c
removed.
09061c
09061c
https://git.ghostscript.com/?p=ghostpdl.git;a=commit;h=1778db6bc10a8d60dfe986b22d2300326733ddd6
09061c
09061c
From: Chris Liddell <chris.liddell@artifex.com>
09061c
Date: Tue, 2 Oct 2018 15:02:58 +0000 (+0100)
09061c
Subject: For hidden operators, pass a name object to error handler.
09061c
09061c
For hidden operators, pass a name object to error handler.
09061c
09061c
In normal operation, Postscript error handlers are passed the object which
09061c
triggered the error: this is invariably an operator object.
09061c
09061c
The issue arises when an error is triggered by an operator which is for internal
09061c
use only, and that operator is then passed to the error handler, meaning it
09061c
becomes visible to the error handler code.
09061c
09061c
By converting to a name object, the error message is still valid, but we no
09061c
longer expose internal use only operators.
09061c
09061c
The change in gs_dps1.ps is related to the above: previously an error in
09061c
scheck would throw an error against .gcheck, but as .gcheck is now a hidden
09061c
operator, it resulted in a name object being passed to the error handler. As
09061c
scheck is a 'real' operator, it's better to use the real operator, rather than
09061c
the name of an internal, hidden one.
09061c
09061c
https://git.ghostscript.com/?p=ghostpdl.git;a=commit;h=a6807394bd94b708be24758287b606154daaaed9
09061c
---
09061c
09061c
diff -up ghostscript-9.07/psi/interp.c.cve-2018-17183 ghostscript-9.07/psi/interp.c
09061c
--- ghostscript-9.07/psi/interp.c.cve-2018-17183	2018-11-30 14:21:33.531815665 +0100
09061c
+++ ghostscript-9.07/psi/interp.c	2018-11-30 14:43:42.520691143 +0100
09061c
@@ -650,20 +650,25 @@ again:
09061c
         return code;
09061c
     if (gs_errorname(i_ctx_p, code, &error_name) < 0)
09061c
         return code;            /* out-of-range error code! */
09061c
-    /*
09061c
-     * For greater Adobe compatibility, only the standard PostScript errors
09061c
-     * are defined in errordict; the rest are in gserrordict.
09061c
+
09061c
+    /*  We refer to gserrordict first, which is not accessible to Postcript jobs
09061c
+     *  If we're running with SAFERERRORS all the handlers are copied to gserrordict
09061c
+     *  so we'll always find the default one. If not SAFERERRORS, only gs specific
09061c
+     *  errors are in gserrordict.
09061c
      */
09061c
-    if (dict_find_string(systemdict, "errordict", &perrordict) <= 0 ||
09061c
+    if (dict_find_string(systemdict, "gserrordict", &perrordict) <= 0 ||
09061c
         (dict_find(perrordict, &error_name, &epref) <= 0 &&
09061c
-         (dict_find_string(systemdict, "gserrordict", &perrordict) <= 0 ||
09061c
+         (dict_find_string(systemdict, "errordict", &perrordict) <= 0 ||
09061c
           dict_find(perrordict, &error_name, &epref) <= 0))
09061c
         )
09061c
         return code;            /* error name not in errordict??? */
09061c
+
09061c
     doref = *epref;
09061c
     epref = &doref;
09061c
     /* Push the error object on the operand stack if appropriate. */
09061c
     if (!ERROR_IS_INTERRUPT(code)) {
09061c
+        byte buf[260], *bufptr;
09061c
+        uint rlen;
09061c
         /* Replace the error object if within an oparray or .errorexec. */
09061c
         osp++;
09061c
         if (osp >= ostop) {
09061c
@@ -672,6 +677,37 @@ again:
09061c
         }
09061c
         *osp = *perror_object;
09061c
         errorexec_find(i_ctx_p, osp);
09061c
+
09061c
+        if (!r_has_type(osp, t_string) && !r_has_type(osp, t_name)) {
09061c
+            code = obj_cvs(imemory, osp, buf + 2, 256, &rlen, (const byte **)&bufptr);
09061c
+            if (code < 0) {
09061c
+                const char *unknownstr = "--unknown--";
09061c
+                rlen = strlen(unknownstr);
09061c
+                memcpy(buf, unknownstr, rlen);
09061c
+                bufptr = buf;
09061c
+            }
09061c
+            else {
09061c
+                ref *tobj;
09061c
+                bufptr[rlen] = '\0';
09061c
+                /* Only pass a name object if the operator doesn't exist in systemdict
09061c
+                 * i.e. it's an internal operator we have hidden
09061c
+                 */
09061c
+                code = dict_find_string(systemdict, (const char *)bufptr, &tobj);
09061c
+                if (code < 0) {
09061c
+                    buf[0] = buf[1] = buf[rlen + 2] = buf[rlen + 3] = '-';
09061c
+                    rlen += 4;
09061c
+                    bufptr = buf;
09061c
+                }
09061c
+                else {
09061c
+                    bufptr = NULL;
09061c
+                }
09061c
+            }
09061c
+            if (bufptr) {
09061c
+                code = name_ref(imemory, buf, rlen, osp, 1);
09061c
+                if (code < 0)
09061c
+                    make_null(osp);
09061c
+            }
09061c
+        }
09061c
     }
09061c
     goto again;
09061c
 }
09061c
diff -up ghostscript-9.07/Resource/Init/gs_dps1.ps.cve-2018-17183 ghostscript-9.07/Resource/Init/gs_dps1.ps
09061c
--- ghostscript-9.07/Resource/Init/gs_dps1.ps.cve-2018-17183	2018-11-30 14:40:30.044460932 +0100
09061c
+++ ghostscript-9.07/Resource/Init/gs_dps1.ps	2018-11-30 14:41:03.291982495 +0100
09061c
@@ -21,7 +21,7 @@ level2dict begin
09061c
 % ------ Virtual memory ------ %
09061c
 
09061c
 /currentshared /.currentglobal load def
09061c
-/scheck /.gcheck load def
09061c
+/scheck {.gcheck} bind odef
09061c
 %****** FOLLOWING IS WRONG ******
09061c
 /shareddict currentdict /globaldict .knownget not { 20 dict } if def
09061c
 
09061c
diff -up ghostscript-9.07/Resource/Init/gs_init.ps.cve-2018-17183 ghostscript-9.07/Resource/Init/gs_init.ps
09061c
--- ghostscript-9.07/Resource/Init/gs_init.ps.cve-2018-17183	2018-11-30 14:16:19.956328097 +0100
09061c
+++ ghostscript-9.07/Resource/Init/gs_init.ps	2018-11-30 14:30:28.051123777 +0100
09061c
@@ -183,6 +183,16 @@ currentdict /DELAYSAFER known { /DELAYSA
09061c
   currentdict /PARANOIDSAFER known or	% PARANOIDSAFER is equivalent
09061c
 }
09061c
 ifelse def
09061c
+
09061c
+/SAFERERRORS
09061c
+currentdict /NOSAFERERRORS known
09061c
+{
09061c
+  //false
09061c
+}
09061c
+{
09061c
+  currentdict /SAFERERRORS known
09061c
+} ifelse def
09061c
+
09061c
 currentdict /SHORTERRORS known   /SHORTERRORS exch def
09061c
 currentdict /STRICT known   /STRICT exch def
09061c
 currentdict /TTYPAUSE known   /TTYPAUSE exch def
09061c
@@ -880,7 +890,7 @@ userdict /.currentresourcefile //null pu
09061c
        { not exch pop exit } { pop } ifelse
09061c
     }
09061c
    for exch pop .quit
09061c
- } bind def
09061c
+ } bind executeonly def
09061c
 /.errorhandler		% <command> <errorname> .errorhandler -
09061c
   {		% Detect an internal 'stopped'.
09061c
     1 .instopped { //null eq { pop pop stop } if } if
09061c
@@ -925,7 +935,7 @@ userdict /.currentresourcefile //null pu
09061c
     $error /globalmode get $error /.nosetlocal get and .setglobal
09061c
     $error /.inerror //false put
09061c
     stop
09061c
-  } bind def
09061c
+  } bind executeonly def
09061c
 % Define the standard handleerror.  We break out the printing procedure
09061c
 % (.printerror) so that it can be extended for binary output
09061c
 % if the Level 2 facilities are present.
09061c
@@ -975,7 +985,7 @@ userdict /.currentresourcefile //null pu
09061c
      ifelse	% newerror
09061c
      end
09061c
      flush
09061c
-    } bind def
09061c
+    } bind executeonly def
09061c
   /.printerror_long			% long error printout,
09061c
                                         % $error is on the dict stack
09061c
    {	% Push the (anonymous) stack printing procedure.
09061c
@@ -1052,14 +1062,14 @@ userdict /.currentresourcefile //null pu
09061c
         { (Current file position is ) print position = }
09061c
        if
09061c
 
09061c
-   } bind def
09061c
+   } bind executeonly def
09061c
 % Define a procedure for clearing the error indication.
09061c
 /.clearerror
09061c
  { $error /newerror //false put
09061c
    $error /errorname //null put
09061c
    $error /errorinfo //null put
09061c
    0 .setoserrno
09061c
- } bind def
09061c
+ } bind executeonly def
09061c
 
09061c
 % Define $error.  This must be in local VM.
09061c
 .currentglobal //false .setglobal
09061c
@@ -1085,11 +1095,15 @@ end
09061c
 /errordict ErrorNames length 3 add dict
09061c
 .forcedef		% errordict is local, systemdict is global
09061c
 .setglobal		% back to global VM
09061c
-% For greater Adobe compatibility, we put all non-standard errors in a
09061c
-%   separate dictionary, gserrordict.  It does not need to be in local VM,
09061c
-%   because PostScript programs do not access it.
09061c
+%  gserrordict contains all the default error handling methods, but unlike
09061c
+%  errordict it is noaccess after creation (also it is in global VM).
09061c
+%  When running 'SAFER', we'll ignore the contents of errordict, which
09061c
+%  may have been tampered with by the running job, and always use gserrordict
09061c
+%  gserrordict also contains any non-standard errors, for better compatibility
09061c
+%  with Adobe.
09061c
+%
09061c
 %   NOTE: the name gserrordict is known to the interpreter.
09061c
-/gserrordict 5 dict def
09061c
+/gserrordict ErrorNames length 3 add dict def
09061c
 % Register an error in errordict.  We make this a procedure because we only
09061c
 % register the Level 1 errors here: the rest are registered by "feature"
09061c
 % files.  However, ErrorNames contains all of the error names regardless of
09061c
@@ -1118,9 +1132,23 @@ errordict begin
09061c
  } bind def
09061c
 end		% errordict
09061c
 
09061c
-% Put non-standard errors in gserrordict.
09061c
 gserrordict /unknownerror errordict /unknownerror get put
09061c
 errordict /unknownerror .undef
09061c
+
09061c
+/.SAFERERRORLIST ErrorNames def
09061c
+/.setsafererrors
09061c
+{
09061c
+% Put all the requested handlers in gserrordict
09061c
+  gserrordict
09061c
+  //.SAFERERRORLIST
09061c
+  {dup errordict exch get 2 index 3 1 roll put} forall
09061c
+  noaccess pop
09061c
+  systemdict /.setsafeerrors .forceundef
09061c
+  systemdict /.SAFERERRORLIST .forceundef
09061c
+} bind executeonly odef
09061c
+
09061c
+SAFERERRORS {.setsafererrors} if
09061c
+
09061c
 % Define a stable private copy of handleerror that we will always use under
09061c
 % JOBSERVER mode.
09061c
 /.GShandleerror errordict /handleerror get def
09061c
@@ -1743,18 +1771,15 @@ currentdict /.runlibfile .undef
09061c
 
09061c
 % Bind all the operators defined as procedures.
09061c
 /.bindoperators		% binds operators in currentdict
09061c
- { % Temporarily disable the typecheck error.
09061c
-   errordict /typecheck 2 copy get
09061c
-   errordict /typecheck { pop } put	% pop the command
09061c
+ {
09061c
    currentdict
09061c
     { dup type /operatortype eq
09061c
-       { % This might be a real operator, so bind might cause a typecheck,
09061c
-         % but we've made the error a no-op temporarily.
09061c
-         .bind		% do a real bind even if NOBIND is set
09061c
+       {
09061c
+         % This might be a real operator, so bind might cause a typecheck
09061c
+         {.bind} .internalstopped pop
09061c
        }
09061c
       if pop pop
09061c
     } forall
09061c
-   put
09061c
  } def
09061c
 NOBIND DELAYBIND or not { .bindoperators } if
09061c