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