diff options
author | Chris Liddell <chris.liddell@artifex.com> | 2018-09-06 09:16:22 +0100 |
---|---|---|
committer | Chris Liddell <chris.liddell@artifex.com> | 2018-09-06 17:14:28 +0100 |
commit | fb713b3818b52d8a6cf62c951eba2e1795ff9624 (patch) | |
tree | 3f5040c6e21730ea5e8dc434612dac8a22007135 | |
parent | 0d8c7d563745bfd89051a203267fcbf2492ecfcc (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.ps | 29 | ||||
-rw-r--r-- | psi/interp.c | 30 |
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 |
1120 | end % errordict | 1124 | end % errordict |
1121 | 1125 | ||
1122 | % Put non-standard errors in gserrordict. | 1126 | % Put all the default handlers in gserrordict |
1123 | gserrordict /unknownerror errordict /unknownerror get put | 1127 | gserrordict |
1128 | errordict {2 index 3 1 roll put} forall | ||
1129 | noaccess pop | ||
1130 | % remove the non-standard errors from errordict | ||
1124 | errordict /unknownerror .undef | 1131 | errordict /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. */ |