|
|
1164f7 |
From: Chris Liddell <chris.liddell@artifex.com>
|
|
|
1164f7 |
Date: Tue, 4 Sep 2018 22:18:46 +0000 (+0100)
|
|
|
1164f7 |
Subject: Bug 699714: retain .LockSafetyParams through failed .installpagedevice
|
|
|
1164f7 |
|
|
|
1164f7 |
Bug 699714: retain .LockSafetyParams through failed .installpagedevice
|
|
|
1164f7 |
|
|
|
1164f7 |
In the event that the .trysetparams fails during .installpagedevice, catch the
|
|
|
1164f7 |
error, and ensure that at least the .LockSafetyParams is set.
|
|
|
1164f7 |
|
|
|
1164f7 |
https://git.ghostscript.com/?p=ghostpdl.git;a=commit;h=5812b1b78fc4d36fdc293b7859de69241140d590
|
|
|
1164f7 |
|
|
|
1164f7 |
From: Chris Liddell <chris.liddell@artifex.com>
|
|
|
1164f7 |
Date: Wed, 5 Sep 2018 16:14:59 +0000 (+0100)
|
|
|
1164f7 |
Subject: Bug 699718: Ensure stack space is available before gsrestore call out
|
|
|
1164f7 |
|
|
|
1164f7 |
Bug 699718: Ensure stack space is available before gsrestore call out
|
|
|
1164f7 |
|
|
|
1164f7 |
During a grestore, if the device is going to change, we call out to Postscript
|
|
|
1164f7 |
to restore the device configuration, before returning to restore the graphics
|
|
|
1164f7 |
state internally.
|
|
|
1164f7 |
|
|
|
1164f7 |
We have to ensure sufficient op stack space is available to complete the
|
|
|
1164f7 |
operation, otherwise the device can end up an undefined state.
|
|
|
1164f7 |
|
|
|
1164f7 |
https://git.ghostscript.com/?p=ghostpdl.git;a=commit;h=3e5d316b72e3965b7968bb1d96baa137cd063ac6
|
|
|
1164f7 |
|
|
|
1164f7 |
From: Chris Liddell <chris.liddell@artifex.com>
|
|
|
1164f7 |
Date: Fri, 7 Sep 2018 07:07:12 +0000 (+0100)
|
|
|
1164f7 |
Subject: Bug 699718(2): Improve/augment stack size checking
|
|
|
1164f7 |
|
|
|
1164f7 |
Bug 699718(2): Improve/augment stack size checking
|
|
|
1164f7 |
|
|
|
1164f7 |
Improve the rebustness of the previous solution (previously it could trigger an
|
|
|
1164f7 |
error when there *was* stack capacity available).
|
|
|
1164f7 |
|
|
|
1164f7 |
Remove redundant check: we don't need to check if the *current* stack size is
|
|
|
1164f7 |
sufficient, before checking the maximum permitted stack size.
|
|
|
1164f7 |
|
|
|
1164f7 |
Also check the exec stack, as execstackoverflow can also cause the
|
|
|
1164f7 |
Postscript call out to fail.
|
|
|
1164f7 |
|
|
|
1164f7 |
Lastly, in event of failure, put the LockSafetyParams flag back in the existing
|
|
|
1164f7 |
device (this is only necessary because we don't enfore JOBSERVER mode).
|
|
|
1164f7 |
|
|
|
1164f7 |
Note: the Postscript callout (%grestorepagedevice) never pushes any dictionaries
|
|
|
1164f7 |
on the dict stack - if that changes, we should check that stack, too.
|
|
|
1164f7 |
|
|
|
1164f7 |
https://git.ghostscript.com/?p=ghostpdl.git;a=commit;h=643b24dbd002fb9c131313253c307cf3951b3d47
|
|
|
1164f7 |
---
|
|
|
1164f7 |
|
|
|
1164f7 |
diff -up ghostscript-9.07/base/gserrors.h.cve-2018-16802 ghostscript-9.07/base/gserrors.h
|
|
|
1164f7 |
--- ghostscript-9.07/base/gserrors.h.cve-2018-16802 2018-11-27 19:07:38.076517822 +0100
|
|
|
1164f7 |
+++ ghostscript-9.07/base/gserrors.h 2018-11-27 19:09:19.116234748 +0100
|
|
|
1164f7 |
@@ -25,6 +25,7 @@
|
|
|
1164f7 |
/* We use ints rather than an enum to avoid a lot of casting. */
|
|
|
1164f7 |
|
|
|
1164f7 |
#define gs_error_unknownerror (-1) /* unknown error */
|
|
|
1164f7 |
+#define gs_error_execstackoverflow (-5)
|
|
|
1164f7 |
#define gs_error_interrupt (-6)
|
|
|
1164f7 |
#define gs_error_invalidaccess (-7)
|
|
|
1164f7 |
#define gs_error_invalidfileaccess (-9)
|
|
|
1164f7 |
@@ -33,6 +34,7 @@
|
|
|
1164f7 |
#define gs_error_limitcheck (-13)
|
|
|
1164f7 |
#define gs_error_nocurrentpoint (-14)
|
|
|
1164f7 |
#define gs_error_rangecheck (-15)
|
|
|
1164f7 |
+#define gs_error_stackoverflow (-16)
|
|
|
1164f7 |
#define gs_error_stackunderflow (-17)
|
|
|
1164f7 |
#define gs_error_typecheck (-20)
|
|
|
1164f7 |
#define gs_error_undefined (-21)
|
|
|
1164f7 |
diff -up ghostscript-9.07/psi/zdevice2.c.cve-2018-16802 ghostscript-9.07/psi/zdevice2.c
|
|
|
1164f7 |
--- ghostscript-9.07/psi/zdevice2.c.cve-2018-16802 2018-11-27 19:04:51.665627148 +0100
|
|
|
1164f7 |
+++ ghostscript-9.07/psi/zdevice2.c 2018-11-27 19:04:51.696626755 +0100
|
|
|
1164f7 |
@@ -250,8 +250,8 @@ z2currentgstate(i_ctx_t *i_ctx_p)
|
|
|
1164f7 |
/* ------ Wrappers for operators that reset the graphics state. ------ */
|
|
|
1164f7 |
|
|
|
1164f7 |
/* Check whether we need to call out to restore the page device. */
|
|
|
1164f7 |
-static bool
|
|
|
1164f7 |
-restore_page_device(const gs_state * pgs_old, const gs_state * pgs_new)
|
|
|
1164f7 |
+static int
|
|
|
1164f7 |
+restore_page_device(i_ctx_t *i_ctx_p, const gs_state * pgs_old, const gs_state * pgs_new)
|
|
|
1164f7 |
{
|
|
|
1164f7 |
gx_device *dev_old = gs_currentdevice(pgs_old);
|
|
|
1164f7 |
gx_device *dev_new;
|
|
|
1164f7 |
@@ -259,9 +259,10 @@ restore_page_device(const gs_state * pgs
|
|
|
1164f7 |
gx_device *dev_t2;
|
|
|
1164f7 |
bool samepagedevice = obj_eq(dev_old->memory, &gs_int_gstate(pgs_old)->pagedevice,
|
|
|
1164f7 |
&gs_int_gstate(pgs_new)->pagedevice);
|
|
|
1164f7 |
+ bool LockSafetyParams = dev_old->LockSafetyParams;
|
|
|
1164f7 |
|
|
|
1164f7 |
if ((dev_t1 = (*dev_proc(dev_old, get_page_device)) (dev_old)) == 0)
|
|
|
1164f7 |
- return false;
|
|
|
1164f7 |
+ return 0;
|
|
|
1164f7 |
/* If we are going to putdeviceparams in a callout, we need to */
|
|
|
1164f7 |
/* unlock temporarily. The device will be re-locked as needed */
|
|
|
1164f7 |
/* by putdeviceparams from the pgs_old->pagedevice dict state. */
|
|
|
1164f7 |
@@ -270,23 +271,51 @@ restore_page_device(const gs_state * pgs
|
|
|
1164f7 |
dev_new = gs_currentdevice(pgs_new);
|
|
|
1164f7 |
if (dev_old != dev_new) {
|
|
|
1164f7 |
if ((dev_t2 = (*dev_proc(dev_new, get_page_device)) (dev_new)) == 0)
|
|
|
1164f7 |
- return false;
|
|
|
1164f7 |
- if (dev_t1 != dev_t2)
|
|
|
1164f7 |
- return true;
|
|
|
1164f7 |
+ samepagedevice = true;
|
|
|
1164f7 |
+ else if (dev_t1 != dev_t2)
|
|
|
1164f7 |
+ samepagedevice = false;
|
|
|
1164f7 |
+ }
|
|
|
1164f7 |
+
|
|
|
1164f7 |
+ if (LockSafetyParams && !samepagedevice) {
|
|
|
1164f7 |
+ const int required_ops = 512;
|
|
|
1164f7 |
+ const int required_es = 32;
|
|
|
1164f7 |
+
|
|
|
1164f7 |
+ /* The %grestorepagedevice must complete: the biggest danger
|
|
|
1164f7 |
+ is operand stack overflow. As we use get/putdeviceparams
|
|
|
1164f7 |
+ that means pushing all the device params onto the stack,
|
|
|
1164f7 |
+ pdfwrite having by far the largest number of parameters
|
|
|
1164f7 |
+ at (currently) 212 key/value pairs - thus needing (currently)
|
|
|
1164f7 |
+ 424 entries on the op stack. Allowing for working stack
|
|
|
1164f7 |
+ space, and safety margin.....
|
|
|
1164f7 |
+ */
|
|
|
1164f7 |
+ if (required_ops + ref_stack_count(&o_stack) >= ref_stack_max_count(&o_stack)) {
|
|
|
1164f7 |
+ gs_currentdevice(pgs_old)->LockSafetyParams = LockSafetyParams;
|
|
|
1164f7 |
+ return_error(gs_error_stackoverflow);
|
|
|
1164f7 |
+ }
|
|
|
1164f7 |
+ /* We also want enough exec stack space - 32 is an overestimate of
|
|
|
1164f7 |
+ what we need to complete the Postscript call out.
|
|
|
1164f7 |
+ */
|
|
|
1164f7 |
+ if (required_es + ref_stack_count(&e_stack) >= ref_stack_max_count(&e_stack)) {
|
|
|
1164f7 |
+ gs_currentdevice(pgs_old)->LockSafetyParams = LockSafetyParams;
|
|
|
1164f7 |
+ return_error(gs_error_execstackoverflow);
|
|
|
1164f7 |
+ }
|
|
|
1164f7 |
}
|
|
|
1164f7 |
/*
|
|
|
1164f7 |
* The current implementation of setpagedevice just sets new
|
|
|
1164f7 |
* parameters in the same device object, so we have to check
|
|
|
1164f7 |
* whether the page device dictionaries are the same.
|
|
|
1164f7 |
*/
|
|
|
1164f7 |
- return !samepagedevice;
|
|
|
1164f7 |
+ return samepagedevice ? 0 : 1;
|
|
|
1164f7 |
}
|
|
|
1164f7 |
|
|
|
1164f7 |
/* - grestore - */
|
|
|
1164f7 |
static int
|
|
|
1164f7 |
z2grestore(i_ctx_t *i_ctx_p)
|
|
|
1164f7 |
{
|
|
|
1164f7 |
- if (!restore_page_device(igs, gs_state_saved(igs)))
|
|
|
1164f7 |
+ int code = restore_page_device(i_ctx_p, igs, gs_state_saved(igs));
|
|
|
1164f7 |
+ if (code < 0) return code;
|
|
|
1164f7 |
+
|
|
|
1164f7 |
+ if (code == 0)
|
|
|
1164f7 |
return gs_grestore(igs);
|
|
|
1164f7 |
return push_callout(i_ctx_p, "%grestorepagedevice");
|
|
|
1164f7 |
}
|
|
|
1164f7 |
@@ -296,7 +325,9 @@ static int
|
|
|
1164f7 |
z2grestoreall(i_ctx_t *i_ctx_p)
|
|
|
1164f7 |
{
|
|
|
1164f7 |
for (;;) {
|
|
|
1164f7 |
- if (!restore_page_device(igs, gs_state_saved(igs))) {
|
|
|
1164f7 |
+ int code = restore_page_device(i_ctx_p, igs, gs_state_saved(igs));
|
|
|
1164f7 |
+ if (code < 0) return code;
|
|
|
1164f7 |
+ if (code == 0) {
|
|
|
1164f7 |
bool done = !gs_state_saved(gs_state_saved(igs));
|
|
|
1164f7 |
|
|
|
1164f7 |
gs_grestore(igs);
|
|
|
1164f7 |
@@ -327,11 +358,15 @@ z2restore(i_ctx_t *i_ctx_p)
|
|
|
1164f7 |
if (code < 0) return code;
|
|
|
1164f7 |
|
|
|
1164f7 |
while (gs_state_saved(gs_state_saved(igs))) {
|
|
|
1164f7 |
- if (restore_page_device(igs, gs_state_saved(igs)))
|
|
|
1164f7 |
+ code = restore_page_device(i_ctx_p, igs, gs_state_saved(igs));
|
|
|
1164f7 |
+ if (code < 0) return code;
|
|
|
1164f7 |
+ if (code > 0)
|
|
|
1164f7 |
return push_callout(i_ctx_p, "%restore1pagedevice");
|
|
|
1164f7 |
gs_grestore(igs);
|
|
|
1164f7 |
}
|
|
|
1164f7 |
- if (restore_page_device(igs, gs_state_saved(igs)))
|
|
|
1164f7 |
+ code = restore_page_device(i_ctx_p, igs, gs_state_saved(igs));
|
|
|
1164f7 |
+ if (code < 0) return code;
|
|
|
1164f7 |
+ if (code > 0)
|
|
|
1164f7 |
return push_callout(i_ctx_p, "%restorepagedevice");
|
|
|
1164f7 |
|
|
|
1164f7 |
code = dorestore(i_ctx_p, asave);
|
|
|
1164f7 |
@@ -354,9 +389,12 @@ static int
|
|
|
1164f7 |
z2setgstate(i_ctx_t *i_ctx_p)
|
|
|
1164f7 |
{
|
|
|
1164f7 |
os_ptr op = osp;
|
|
|
1164f7 |
+ int code;
|
|
|
1164f7 |
|
|
|
1164f7 |
check_stype(*op, st_igstate_obj);
|
|
|
1164f7 |
- if (!restore_page_device(igs, igstate_ptr(op)))
|
|
|
1164f7 |
+ code = restore_page_device(i_ctx_p, igs, igstate_ptr(op));
|
|
|
1164f7 |
+ if (code < 0) return code;
|
|
|
1164f7 |
+ if (code == 0)
|
|
|
1164f7 |
return zsetgstate(i_ctx_p);
|
|
|
1164f7 |
return push_callout(i_ctx_p, "%setgstatepagedevice");
|
|
|
1164f7 |
}
|
|
|
1164f7 |
diff -up ghostscript-9.07/Resource/Init/gs_setpd.ps.cve-2018-16802 ghostscript-9.07/Resource/Init/gs_setpd.ps
|
|
|
1164f7 |
--- ghostscript-9.07/Resource/Init/gs_setpd.ps.cve-2018-16802 2013-02-14 08:58:16.000000000 +0100
|
|
|
1164f7 |
+++ ghostscript-9.07/Resource/Init/gs_setpd.ps 2018-11-27 19:04:51.696626755 +0100
|
|
|
1164f7 |
@@ -95,27 +95,41 @@ level2dict begin
|
|
|
1164f7 |
{ % Since setpagedevice doesn't create new device objects,
|
|
|
1164f7 |
% we must (carefully) reinstall the old parameters in
|
|
|
1164f7 |
% the same device.
|
|
|
1164f7 |
- .currentpagedevice pop //null currentdevice //null .trysetparams
|
|
|
1164f7 |
+ .currentpagedevice pop //null currentdevice //null
|
|
|
1164f7 |
+ { .trysetparams } .internalstopped
|
|
|
1164f7 |
+ {
|
|
|
1164f7 |
+ //null
|
|
|
1164f7 |
+ } if
|
|
|
1164f7 |
dup type /booleantype eq
|
|
|
1164f7 |
{ pop pop }
|
|
|
1164f7 |
- { % This should never happen!
|
|
|
1164f7 |
+ {
|
|
|
1164f7 |
SETPDDEBUG { (Error in .trysetparams!) = pstack flush } if
|
|
|
1164f7 |
- cleartomark pop pop pop
|
|
|
1164f7 |
+ {cleartomark pop pop pop} .internalstopped pop
|
|
|
1164f7 |
+ % if resetting the entire device state failed, at least put back the
|
|
|
1164f7 |
+ % security related key
|
|
|
1164f7 |
+ currentdevice //null //false mark /.LockSafetyParams
|
|
|
1164f7 |
+ currentpagedevice /.LockSafetyParams .knownget not
|
|
|
1164f7 |
+ {systemdict /SAFER .knownget not {//false} } if
|
|
|
1164f7 |
+ .putdeviceparamsonly
|
|
|
1164f7 |
/.installpagedevice cvx /rangecheck signalerror
|
|
|
1164f7 |
}
|
|
|
1164f7 |
ifelse pop pop
|
|
|
1164f7 |
% A careful reading of the Red Book reveals that an erasepage
|
|
|
1164f7 |
% should occur, but *not* an initgraphics.
|
|
|
1164f7 |
erasepage .beginpage
|
|
|
1164f7 |
- } bind def
|
|
|
1164f7 |
+ } bind executeonly def
|
|
|
1164f7 |
|
|
|
1164f7 |
/.uninstallpagedevice
|
|
|
1164f7 |
- { 2 .endpage { .currentnumcopies //false .outputpage } if
|
|
|
1164f7 |
+ {
|
|
|
1164f7 |
+ {2 .endpage { .currentnumcopies //false .outputpage } if} .internalstopped pop
|
|
|
1164f7 |
nulldevice
|
|
|
1164f7 |
} bind def
|
|
|
1164f7 |
|
|
|
1164f7 |
(%grestorepagedevice) cvn
|
|
|
1164f7 |
- { .uninstallpagedevice grestore .installpagedevice
|
|
|
1164f7 |
+ {
|
|
|
1164f7 |
+ .uninstallpagedevice
|
|
|
1164f7 |
+ grestore
|
|
|
1164f7 |
+ .installpagedevice
|
|
|
1164f7 |
} bind def
|
|
|
1164f7 |
|
|
|
1164f7 |
(%grestoreallpagedevice) cvn
|