summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Liddell <chris.liddell@artifex.com>2018-09-06 09:16:22 +0100
committerChris Liddell <chris.liddell@artifex.com>2018-09-06 17:14:28 +0100
commitfb713b3818b52d8a6cf62c951eba2e1795ff9624 (patch)
tree3f5040c6e21730ea5e8dc434612dac8a22007135
parent0d8c7d563745bfd89051a203267fcbf2492ecfcc (diff)
Bug 699708 (part 1): 'Hide' non-replaceable error handlers for SAFER
We already had a 'private' dictionary for non-standard errors: gserrordict. This now includes all the default error handlers, the dictionary is made noaccess and all the prodedures are bound and executeonly. When running with -dSAFER, in the event of a Postscript error, instead of pulling the handler from errordict, we'll pull it from gserrordict - thus malicious input cannot trigger problems by the use of custom error handlers. errordict remains open and writeable, so files such as the Quality Logic tests that install their own handlers will still 'work', with the exception that the custom error handlers will not be called. This is a 'first pass', 'sledgehammer' approach: a nice addition would to allow an integrator to specify a list of errors that are not to be replaced (for example, embedded applications would probably want to ensure that VMerror is always handled as they intend).
-rw-r--r--Resource/Init/gs_init.ps29
-rw-r--r--psi/interp.c30
2 files changed, 39 insertions, 20 deletions
diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
index 071c39205..bc8b7951c 100644
--- a/Resource/Init/gs_init.ps
+++ b/Resource/Init/gs_init.ps
@@ -881,7 +881,7 @@ userdict /.currentresourcefile //null put
881 { not exch pop exit } { pop } ifelse 881 { not exch pop exit } { pop } ifelse
882 } 882 }
883 for exch pop .quit 883 for exch pop .quit
884 } bind def 884 } bind executeonly def
885/.errorhandler % <command> <errorname> .errorhandler - 885/.errorhandler % <command> <errorname> .errorhandler -
886 { % Detect an internal 'stopped'. 886 { % Detect an internal 'stopped'.
887 1 .instopped { //null eq { pop pop stop } if } if 887 1 .instopped { //null eq { pop pop stop } if } if
@@ -926,7 +926,7 @@ userdict /.currentresourcefile //null put
926 $error /globalmode get $error /.nosetlocal get and .setglobal 926 $error /globalmode get $error /.nosetlocal get and .setglobal
927 $error /.inerror //false put 927 $error /.inerror //false put
928 stop 928 stop
929 } bind def 929 } bind executeonly def
930% Define the standard handleerror. We break out the printing procedure 930% Define the standard handleerror. We break out the printing procedure
931% (.printerror) so that it can be extended for binary output 931% (.printerror) so that it can be extended for binary output
932% if the Level 2 facilities are present. 932% if the Level 2 facilities are present.
@@ -976,7 +976,7 @@ userdict /.currentresourcefile //null put
976 ifelse % newerror 976 ifelse % newerror
977 end 977 end
978 flush 978 flush
979 } bind def 979 } bind executeonly def
980 /.printerror_long % long error printout, 980 /.printerror_long % long error printout,
981 % $error is on the dict stack 981 % $error is on the dict stack
982 { % Push the (anonymous) stack printing procedure. 982 { % Push the (anonymous) stack printing procedure.
@@ -1053,14 +1053,14 @@ userdict /.currentresourcefile //null put
1053 { (Current file position is ) print position = } 1053 { (Current file position is ) print position = }
1054 if 1054 if
1055 1055
1056 } bind def 1056 } bind executeonly def
1057% Define a procedure for clearing the error indication. 1057% Define a procedure for clearing the error indication.
1058/.clearerror 1058/.clearerror
1059 { $error /newerror //false put 1059 { $error /newerror //false put
1060 $error /errorname //null put 1060 $error /errorname //null put
1061 $error /errorinfo //null put 1061 $error /errorinfo //null put
1062 0 .setoserrno 1062 0 .setoserrno
1063 } bind def 1063 } bind executeonly def
1064 1064
1065% Define $error. This must be in local VM. 1065% Define $error. This must be in local VM.
1066.currentglobal //false .setglobal 1066.currentglobal //false .setglobal
@@ -1086,11 +1086,15 @@ end
1086/errordict ErrorNames length 3 add dict 1086/errordict ErrorNames length 3 add dict
1087.forcedef % errordict is local, systemdict is global 1087.forcedef % errordict is local, systemdict is global
1088.setglobal % back to global VM 1088.setglobal % back to global VM
1089% For greater Adobe compatibility, we put all non-standard errors in a 1089% gserrordict contains all the default error handling methods, but unlike
1090% separate dictionary, gserrordict. It does not need to be in local VM, 1090% errordict it is noaccess after creation (also it is in global VM).
1091% because PostScript programs do not access it. 1091% When running 'SAFER', we'll ignore the contents of errordict, which
1092% may have been tampered with by the running job, and always use gserrordict
1093% gserrordict also contains any non-standard errors, for better compatibility
1094% with Adobe.
1095%
1092% NOTE: the name gserrordict is known to the interpreter. 1096% NOTE: the name gserrordict is known to the interpreter.
1093/gserrordict 5 dict def 1097/gserrordict ErrorNames length 3 add dict def
1094% Register an error in errordict. We make this a procedure because we only 1098% Register an error in errordict. We make this a procedure because we only
1095% register the Level 1 errors here: the rest are registered by "feature" 1099% register the Level 1 errors here: the rest are registered by "feature"
1096% files. However, ErrorNames contains all of the error names regardless of 1100% files. However, ErrorNames contains all of the error names regardless of
@@ -1119,8 +1123,11 @@ errordict begin
1119 } bind def 1123 } bind def
1120end % errordict 1124end % errordict
1121 1125
1122% Put non-standard errors in gserrordict. 1126% Put all the default handlers in gserrordict
1123gserrordict /unknownerror errordict /unknownerror get put 1127gserrordict
1128errordict {2 index 3 1 roll put} forall
1129noaccess pop
1130% remove the non-standard errors from errordict
1124errordict /unknownerror .undef 1131errordict /unknownerror .undef
1125% Define a stable private copy of handleerror that we will always use under 1132% Define a stable private copy of handleerror that we will always use under
1126% JOBSERVER mode. 1133% JOBSERVER mode.
diff --git a/psi/interp.c b/psi/interp.c
index c27b70dca..d41a9d3f5 100644
--- a/psi/interp.c
+++ b/psi/interp.c
@@ -661,16 +661,28 @@ again:
661 return code; 661 return code;
662 if (gs_errorname(i_ctx_p, code, &error_name) < 0) 662 if (gs_errorname(i_ctx_p, code, &error_name) < 0)
663 return code; /* out-of-range error code! */ 663 return code; /* out-of-range error code! */
664 /* 664
665 * For greater Adobe compatibility, only the standard PostScript errors 665 /* If LockFilePermissions is true, we only refer to gserrordict, which
666 * are defined in errordict; the rest are in gserrordict. 666 * is not accessible to Postcript jobs
667 */ 667 */
668 if (dict_find_string(systemdict, "errordict", &perrordict) <= 0 || 668 if (i_ctx_p->LockFilePermissions) {
669 (dict_find(perrordict, &error_name, &epref) <= 0 && 669 if (((dict_find_string(systemdict, "gserrordict", &perrordict) <= 0 ||
670 (dict_find_string(systemdict, "gserrordict", &perrordict) <= 0 || 670 dict_find(perrordict, &error_name, &epref) <= 0))
671 dict_find(perrordict, &error_name, &epref) <= 0)) 671 )
672 ) 672 return code; /* error name not in errordict??? */
673 return code; /* error name not in errordict??? */ 673 }
674 else {
675 /*
676 * For greater Adobe compatibility, only the standard PostScript errors
677 * are defined in errordict; the rest are in gserrordict.
678 */
679 if (dict_find_string(systemdict, "errordict", &perrordict) <= 0 ||
680 (dict_find(perrordict, &error_name, &epref) <= 0 &&
681 (dict_find_string(systemdict, "gserrordict", &perrordict) <= 0 ||
682 dict_find(perrordict, &error_name, &epref) <= 0))
683 )
684 return code; /* error name not in errordict??? */
685 }
674 doref = *epref; 686 doref = *epref;
675 epref = &doref; 687 epref = &doref;
676 /* Push the error object on the operand stack if appropriate. */ 688 /* Push the error object on the operand stack if appropriate. */