Blob Blame History Raw
From: Ray Johnston <ray.johnston@artifex.com>
Date: Thu, 14 Feb 2019 18:20:03 +0000 (-0800)
Subject: Fix bug 700585: Restrict superexec and remove it from internals and gs_cet.ps

Fix bug 700585: Restrict superexec and remove it from internals and gs_cet.ps

Also while changing things, restructure the CETMODE so that it will
work with -dSAFER. The gs_cet.ps is now run when we are still at save
level 0 with systemdict writeable. Allows us to undefine .makeoperator
and .setCPSImode internal operators after CETMODE is handled.

Change previous uses of superexec to using .forceput (with the usual
.bind executeonly to hide it).

https://git.ghostscript.com/?p=ghostpdl.git;a=commit;h=205591753126802da850ada6511a0ff8411aa287

From: Ray Johnston <ray.johnston@artifex.com>
Date: Mon, 25 Feb 2019 06:01:04 +0000 (-0800)
Subject: Bug 700585: Obliterate "superexec". We don't need it, nor do any known apps.

Bug 700585: Obliterate "superexec". We don't need it, nor do any known apps.

We were under the impression that the Windows driver 'PScript5.dll' used
superexec, but after testing with our extensive suite of PostScript file,
and analysis of the PScript5 "Adobe CoolType ProcSet, it does not appear
that this operator is needed anymore. Get rid of superexec and all of the
references to it, since it is a potential security hole.

https://git.ghostscript.com/?p=ghostpdl.git;a=commit;h=d683d1e6450d74619e6277efeebfc222d9a5cb91
---

diff -up ghostscript-9.07/psi/icontext.c.cve-2019-3835 ghostscript-9.07/psi/icontext.c
--- ghostscript-9.07/psi/icontext.c.cve-2019-3835	2019-02-28 14:32:31.762961195 +0100
+++ ghostscript-9.07/psi/icontext.c	2019-02-28 14:33:02.960552388 +0100
@@ -148,7 +148,6 @@ context_state_alloc(gs_context_state_t *
     pcst->rand_state = rand_state_initial;
     pcst->usertime_total = 0;
     pcst->keep_usertime = false;
-    pcst->in_superexec = 0;
     pcst->plugin_list = 0;
     make_t(&pcst->error_object, t__invalid);
     {	/*
diff -up ghostscript-9.07/psi/icstate.h.cve-2019-3835 ghostscript-9.07/psi/icstate.h
--- ghostscript-9.07/psi/icstate.h.cve-2019-3835	2019-02-28 14:33:38.288089462 +0100
+++ ghostscript-9.07/psi/icstate.h	2019-02-28 14:33:46.576980845 +0100
@@ -52,7 +52,6 @@ struct gs_context_state_s {
     long usertime_total;	/* total accumulated usertime, */
                                 /* not counting current time if running */
     bool keep_usertime;		/* true if context ever executed usertime */
-    int in_superexec;		/* # of levels of superexec */
     /* View clipping is handled in the graphics state. */
     ref error_object;		/* t__invalid or error object from operator */
     ref userparams;		/* t_dictionary */
diff -up ghostscript-9.07/psi/zcontrol.c.cve-2019-3835 ghostscript-9.07/psi/zcontrol.c
--- ghostscript-9.07/psi/zcontrol.c.cve-2019-3835	2019-02-28 14:34:07.694704120 +0100
+++ ghostscript-9.07/psi/zcontrol.c	2019-02-28 14:34:44.573220870 +0100
@@ -158,34 +158,6 @@ zexecn(i_ctx_t *i_ctx_p)
     return o_push_estack;
 }
 
-/* <obj> superexec - */
-static int end_superexec(i_ctx_t *);
-static int
-zsuperexec(i_ctx_t *i_ctx_p)
-{
-    os_ptr op = osp;
-    es_ptr ep;
-
-    check_op(1);
-    if (!r_has_attr(op, a_executable))
-        return 0;		/* literal object just gets pushed back */
-    check_estack(2);
-    ep = esp += 3;
-    make_mark_estack(ep - 2, es_other, end_superexec); /* error case */
-    make_op_estack(ep - 1,  end_superexec); /* normal case */
-    ref_assign(ep, op);
-    esfile_check_cache();
-    pop(1);
-    i_ctx_p->in_superexec++;
-    return o_push_estack;
-}
-static int
-end_superexec(i_ctx_t *i_ctx_p)
-{
-    i_ctx_p->in_superexec--;
-    return 0;
-}
-
 /* <array> <executable> .runandhide <obj>				*/
 /* 	before executing  <executable>, <array> is been removed from	*/
 /*	the operand stack and placed on the execstack with attributes	*/
@@ -969,8 +941,6 @@ const op_def zcontrol3_op_defs[] = {
     {"0%loop_continue", loop_continue},
     {"0%repeat_continue", repeat_continue},
     {"0%stopped_push", stopped_push},
-    {"1superexec", zsuperexec},
-    {"0%end_superexec", end_superexec},
     {"2.runandhide", zrunandhide},
     {"0%end_runandhide", end_runandhide},
     op_def_end(0)
diff -up ghostscript-9.07/psi/zdict.c.cve-2019-3835 ghostscript-9.07/psi/zdict.c
--- ghostscript-9.07/psi/zdict.c.cve-2019-3835	2019-02-28 14:35:18.029782463 +0100
+++ ghostscript-9.07/psi/zdict.c	2019-02-28 14:36:27.964866049 +0100
@@ -211,8 +211,7 @@ zundef(i_ctx_t *i_ctx_p)
     int code;
 
     check_type(*op1, t_dictionary);
-    if (i_ctx_p->in_superexec == 0)
-        check_dict_write(*op1);
+    check_dict_write(*op1);
     code = idict_undef(op1, op);
     if (code < 0 && code != e_undefined) /* ignore undefined error */
         return code;
@@ -491,8 +490,7 @@ zsetmaxlength(i_ctx_t *i_ctx_p)
     int code;
 
     check_type(*op1, t_dictionary);
-    if (i_ctx_p->in_superexec == 0)
-        check_dict_write(*op1);
+    check_dict_write(*op1);
     check_type(*op, t_integer);
     if (op->value.intval < 0)
         return_error(e_rangecheck);
diff -up ghostscript-9.07/psi/zgeneric.c.cve-2019-3835 ghostscript-9.07/psi/zgeneric.c
--- ghostscript-9.07/psi/zgeneric.c.cve-2019-3835	2019-02-28 14:36:54.684515917 +0100
+++ ghostscript-9.07/psi/zgeneric.c	2019-02-28 14:37:44.859858421 +0100
@@ -204,8 +204,7 @@ zput(i_ctx_t *i_ctx_p)
 
     switch (r_type(op2)) {
         case t_dictionary:
-            if (i_ctx_p->in_superexec == 0)
-                check_dict_write(*op2);
+            check_dict_write(*op2);
             {
                 int code = idict_put(op2, op1, op);
 
diff -up ghostscript-9.07/Resource/Init/gs_cet.ps.cve-2019-3835 ghostscript-9.07/Resource/Init/gs_cet.ps
--- ghostscript-9.07/Resource/Init/gs_cet.ps.cve-2019-3835	2019-02-28 14:24:02.885629428 +0100
+++ ghostscript-9.07/Resource/Init/gs_cet.ps	2019-02-28 14:24:02.908629127 +0100
@@ -1,27 +1,22 @@
-%!PS
 % Set defaults for Ghostscript to match Adobe CPSI behaviour for CET
 
-% do this in the server level so it is persistent across jobs
-//true 0 startjob not {
-  (*** Warning: CET startup is not in server default) = flush
-} if
+% Note: this must be run at save level 0 and when systemdict is writeable
+currentglobal //true setglobal
+systemdict dup dup dup
+/version (3017.102) readonly .forceput         % match CPSI 3017.102
+/product (PhotoPRINT SE 5.0v2) readonly .forceput      % match CPSI 3017.102
+/revision 0 put                        % match CPSI 3017.103 Tek shows revision 5
+/serialnumber dup {233640} readonly .makeoperator .forceput % match CPSI 3017.102 Tek shows serialnumber 1401788461
+
+systemdict /.odef {           % <name> <proc> odef -
+  1 index exch //.makeoperator def
+} .bind .forceput          % this will be undefined at the end
 
 300 .sethiresscreen	% needed for language switch build since it
                         % processes gs_init.ps BEFORE setting the resolution
 
 0 array 0 setdash % CET 09-08 wants local setdash
 
-currentglobal //true setglobal
-
-{
-  systemdict dup dup dup
-  /version (3017.102) readonly put		% match CPSI 3017.102
-  /product (PhotoPRINT SE 5.0v2) readonly put	% match CPSI 3017.102
-  /revision 0 put			% match CPSI 3017.103 Tek shows revision 5
-  /serialnumber dup {233640} readonly .makeoperator put % match CPSI 3017.102 Tek shows serialnumber 1401788461
-  systemdict /deviceinfo undef                  % for CET 20-23-1
-} 1183615869 internaldict /superexec get exec
-
 { } bind dup
 setblackgeneration
 setundercolorremoval
@@ -69,4 +64,4 @@ userdict /.smoothness currentsmoothness
 } bind odef
 /currentsmoothness { userdict /.smoothness get } bind odef % for 09-55.PS, 09-57.PS .
 
-//false 0 startjob pop		% re-enter encapsulated mode
+systemdict /.odef .undef
diff -up ghostscript-9.07/Resource/Init/gs_dps1.ps.cve-2019-3835 ghostscript-9.07/Resource/Init/gs_dps1.ps
--- ghostscript-9.07/Resource/Init/gs_dps1.ps.cve-2019-3835	2019-02-28 14:24:02.892629336 +0100
+++ ghostscript-9.07/Resource/Init/gs_dps1.ps	2019-02-28 14:24:02.908629127 +0100
@@ -86,7 +86,7 @@ level2dict begin
                 % definition, copy it into the local directory.
       //systemdict /SharedFontDirectory .knownget
        { 1 index .knownget
-          { //.FontDirectory 2 index 3 -1 roll { put } systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse } % readonly
+          { //.FontDirectory 2 index 3 -1 roll .forceput } % readonly
          if
        }
       if
diff -up ghostscript-9.07/Resource/Init/gs_fonts.ps.cve-2019-3835 ghostscript-9.07/Resource/Init/gs_fonts.ps
--- ghostscript-9.07/Resource/Init/gs_fonts.ps.cve-2019-3835	2019-02-28 14:24:02.898629257 +0100
+++ ghostscript-9.07/Resource/Init/gs_fonts.ps	2019-02-28 14:24:02.908629127 +0100
@@ -501,11 +501,11 @@ buildfontdict 3 /.buildfont3 cvx put
                 % the font in LocalFontDirectory.
    .currentglobal
     { //systemdict /LocalFontDirectory .knownget
-       { 2 index 2 index { .growput } systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse }  % readonly
+       { 2 index 2 index .forceput }   % readonly
       if
     }
    if
-   dup //.FontDirectory 4 -2 roll { .growput } systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse   % readonly
+   dup //.FontDirectory 4 -2 roll .forceput % readonly
                 % If the font originated as a resource, register it.
    currentfile .currentresourcefile eq { dup .registerfont } if
    readonly
@@ -1149,12 +1149,12 @@ currentdict /.putgstringcopy .forceundef
         //.FontDirectory 1 index known not {
           2 dict dup /FontName 3 index put
           dup /FontType 1 put
-          //.FontDirectory 3 1 roll { put } systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse   % readonly
+          //.FontDirectory 3 1 roll //.forceput exec % readonly
         } {
           pop
         } ifelse
       } forall
-    }
+    } executeonly      % hide .forceput
 FAKEFONTS { exch } if pop def   % don't bind, .current/setglobal get redefined
 
 % Install initial fonts from Fontmap.
diff -up ghostscript-9.07/Resource/Init/gs_init.ps.cve-2019-3835 ghostscript-9.07/Resource/Init/gs_init.ps
--- ghostscript-9.07/Resource/Init/gs_init.ps.cve-2019-3835	2019-02-28 14:24:02.906629153 +0100
+++ ghostscript-9.07/Resource/Init/gs_init.ps	2019-02-28 14:29:40.355207303 +0100
@@ -2125,9 +2125,6 @@ SAFER { .setsafe } if
   /.endtransparencygroup     % transparency-example.ps
   /.setdotlength             % Bug687720.ps
   /.sort /.setdebug /.mementolistnewblocks /getenv
-
-  /.makeoperator /.setCPSImode              % gs_cet.ps, this won't work on cluster with -dSAFER
-
   /unread
   ]
   {systemdict exch .forceundef} forall
@@ -2206,7 +2203,6 @@ SAFER { .setsafe } if
 
   % Used by our own test suite files
   %/.fileposition %image-qa.ps
-  %/.makeoperator /.setCPSImode % gs_cet.ps
 
   % Either our code uses these in ways which mean they can't be undefined, or they are used directly by
   % test files/utilities, or engineers expressed a desire to keep them visible.
@@ -2400,6 +2396,16 @@ end
 /vmreclaim where
  { pop NOGC not { 2 .vmreclaim 0 vmreclaim } if
  } if
+
+% Do this before systemdict is locked (see below for additional CETMODE setup using gs_cet.ps)
+systemdict /CETMODE .knownget {
+  {
+    (gs_cet.ps) runlibfile
+  } if
+} if
+systemdict /.makeoperator .undef       % must be after gs_cet.ps
+systemdict /.setCPSImode .undef                % must be after gs_cet.ps
+
 DELAYBIND not {
   systemdict /.bindnow .undef       % We only need this for DELAYBIND
   systemdict /.forcecopynew .undef	% remove temptation
@@ -2407,11 +2413,6 @@ DELAYBIND not {
   systemdict /.forceput .undef		% ditto
   systemdict /.forceundef .undef	% ditto
 } if
-% Move superexec to internaldict if superexec is defined.
-systemdict /superexec .knownget {
-  1183615869 internaldict /superexec 3 -1 roll put
-  systemdict /superexec .undef
-} if
 
 % Can't remove this one until the last minute :-)
 systemdict /.undef .undef
diff -up ghostscript-9.07/Resource/Init/gs_type1.ps.cve-2019-3835 ghostscript-9.07/Resource/Init/gs_type1.ps
--- ghostscript-9.07/Resource/Init/gs_type1.ps.cve-2019-3835	2019-02-28 14:24:02.886629415 +0100
+++ ghostscript-9.07/Resource/Init/gs_type1.ps	2019-02-28 14:24:02.909629113 +0100
@@ -66,11 +66,11 @@
        2 index 1 index known {
          pop pop
        } {
-         3 1 roll get //.growput systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse dup dup
+         3 1 roll get .forceput dup dup
        } ifelse
      } {
        2 index 1 index known {
-         exch 3 1 roll get //.growput systemdict /superexec known {//superexec}{1183615869 internaldict /superexec get exec} ifelse dup dup
+         exch 3 1 roll get .forceput dup dup
        } {
          pop pop
        } ifelse
@@ -80,7 +80,7 @@
 
    //.buildfont1
    3 2 roll .setglobal
- } bind def
+ } .bind executeonly def       % hide .forceput
 
 % If the diskfont feature isn't included, define a dummy .loadfontdict.
 /.loadfontdict where