gs: apply fixes for CVE-2018-16509 (thanks jsmoody)
This commit is contained in:
parent
197ff3ac2f
commit
e55778d67e
6 changed files with 102 additions and 24 deletions
|
@ -1992,6 +1992,17 @@ readonly def
|
||||||
% If we are running in SAFER mode, lock things down
|
% If we are running in SAFER mode, lock things down
|
||||||
SAFER { .setsafe } if
|
SAFER { .setsafe } if
|
||||||
|
|
||||||
|
/UndefinePostScriptOperators {
|
||||||
|
[
|
||||||
|
/condition /currentcontext /detach /.fork /join /.localfork /lock /monitor /notify
|
||||||
|
/wait /yield /.currentscreenphase /.setscreenphase /.image2 /eoviewclip /initviewclip
|
||||||
|
/viewclip /viewclippath /defineusername
|
||||||
|
/currentalpha /setalpha /.alphaimage /composite /compositerect /dissolve /sizeimagebox /.sizeimageparams
|
||||||
|
]
|
||||||
|
{systemdict exch .forceundef} forall
|
||||||
|
//systemdict /UndefinePostScriptOperators .forceundef
|
||||||
|
} bind def
|
||||||
|
|
||||||
% If we delayed binding, make it possible to do it later.
|
% If we delayed binding, make it possible to do it later.
|
||||||
/.bindnow {
|
/.bindnow {
|
||||||
currentuserparams /IdiomRecognition .knownget {
|
currentuserparams /IdiomRecognition .knownget {
|
||||||
|
@ -2005,6 +2016,7 @@ SAFER { .setsafe } if
|
||||||
//systemdict /.delaybind {} .forceput % reclaim the space
|
//systemdict /.delaybind {} .forceput % reclaim the space
|
||||||
//systemdict /.bindnow .forceundef % ditto
|
//systemdict /.bindnow .forceundef % ditto
|
||||||
put
|
put
|
||||||
|
//systemdict /UndefinePostScriptOperators get exec
|
||||||
//systemdict /.forcedef .forceundef % remove temptation
|
//systemdict /.forcedef .forceundef % remove temptation
|
||||||
//systemdict /.forceput .forceundef % ditto
|
//systemdict /.forceput .forceundef % ditto
|
||||||
//systemdict /.forceundef .forceundef % ditto
|
//systemdict /.forceundef .forceundef % ditto
|
||||||
|
|
|
@ -1992,6 +1992,17 @@ readonly def
|
||||||
% If we are running in SAFER mode, lock things down
|
% If we are running in SAFER mode, lock things down
|
||||||
SAFER { .setsafe } if
|
SAFER { .setsafe } if
|
||||||
|
|
||||||
|
/UndefinePostScriptOperators {
|
||||||
|
[
|
||||||
|
/condition /currentcontext /detach /.fork /join /.localfork /lock /monitor /notify
|
||||||
|
/wait /yield /.currentscreenphase /.setscreenphase /.image2 /eoviewclip /initviewclip
|
||||||
|
/viewclip /viewclippath /defineusername
|
||||||
|
/currentalpha /setalpha /.alphaimage /composite /compositerect /dissolve /sizeimagebox /.sizeimageparams
|
||||||
|
]
|
||||||
|
{systemdict exch .forceundef} forall
|
||||||
|
//systemdict /UndefinePostScriptOperators .forceundef
|
||||||
|
} bind def
|
||||||
|
|
||||||
% If we delayed binding, make it possible to do it later.
|
% If we delayed binding, make it possible to do it later.
|
||||||
/.bindnow {
|
/.bindnow {
|
||||||
currentuserparams /IdiomRecognition .knownget {
|
currentuserparams /IdiomRecognition .knownget {
|
||||||
|
@ -2005,6 +2016,7 @@ SAFER { .setsafe } if
|
||||||
//systemdict /.delaybind {} .forceput % reclaim the space
|
//systemdict /.delaybind {} .forceput % reclaim the space
|
||||||
//systemdict /.bindnow .forceundef % ditto
|
//systemdict /.bindnow .forceundef % ditto
|
||||||
put
|
put
|
||||||
|
//systemdict /UndefinePostScriptOperators get exec
|
||||||
//systemdict /.forcedef .forceundef % remove temptation
|
//systemdict /.forcedef .forceundef % remove temptation
|
||||||
//systemdict /.forceput .forceundef % ditto
|
//systemdict /.forceput .forceundef % ditto
|
||||||
//systemdict /.forceundef .forceundef % ditto
|
//systemdict /.forceundef .forceundef % ditto
|
||||||
|
|
|
@ -480,21 +480,30 @@ gx_device_retain(gx_device *dev, bool retained)
|
||||||
int
|
int
|
||||||
gs_nulldevice(gs_state * pgs)
|
gs_nulldevice(gs_state * pgs)
|
||||||
{
|
{
|
||||||
|
int code = 0;
|
||||||
|
int saveLockSafety = false;
|
||||||
|
|
||||||
if (pgs->device == 0 || !gx_device_is_null(pgs->device)) {
|
if (pgs->device == 0 || !gx_device_is_null(pgs->device)) {
|
||||||
gx_device *ndev;
|
gx_device *ndev;
|
||||||
int code = gs_copydevice(&ndev, (const gx_device *)&gs_null_device,
|
code = gs_copydevice(&ndev, (const gx_device *)&gs_null_device, pgs->memory);
|
||||||
pgs->memory);
|
|
||||||
|
|
||||||
if (code < 0)
|
if (code < 0)
|
||||||
return code;
|
return code;
|
||||||
|
if (gs_currentdevice_inline(pgs) != NULL)
|
||||||
|
saveLockSafety = gs_currentdevice_inline(pgs)->LockSafetyParams;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Internal devices have a reference count of 0, not 1,
|
* Internal devices have a reference count of 0, not 1,
|
||||||
* aside from references from graphics states.
|
* aside from references from graphics states.
|
||||||
*/
|
*/
|
||||||
rc_init(ndev, pgs->memory, 0);
|
rc_init(ndev, pgs->memory, 0);
|
||||||
return gs_setdevice_no_erase(pgs, ndev);
|
code = gs_setdevice_no_erase(pgs, ndev);
|
||||||
|
if (code < 0) {
|
||||||
|
gs_free_object(pgs->memory, ndev, "gs_copydevice(device)");
|
||||||
|
return code;
|
||||||
}
|
}
|
||||||
return 0;
|
gs_currentdevice_inline(pgs)->LockSafetyParams = saveLockSafety;
|
||||||
|
}
|
||||||
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Close a device. The client is responsible for ensuring that */
|
/* Close a device. The client is responsible for ensuring that */
|
||||||
|
|
|
@ -116,4 +116,8 @@ void alloc_set_not_in_save(gs_dual_memory_t *);
|
||||||
/* Remove entries from font and character caches. */
|
/* Remove entries from font and character caches. */
|
||||||
void font_restore(const alloc_save_t * save);
|
void font_restore(const alloc_save_t * save);
|
||||||
|
|
||||||
|
int restore_check_save(i_ctx_t *i_ctx_p, alloc_save_t **asave);
|
||||||
|
|
||||||
|
int dorestore(i_ctx_t *i_ctx_p, alloc_save_t *asave);
|
||||||
|
|
||||||
#endif /* isave_INCLUDED */
|
#endif /* isave_INCLUDED */
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "igstate.h"
|
#include "igstate.h"
|
||||||
#include "iname.h"
|
#include "iname.h"
|
||||||
#include "iutil.h"
|
#include "iutil.h"
|
||||||
|
#include "isave.h"
|
||||||
#include "store.h"
|
#include "store.h"
|
||||||
#include "gxdevice.h"
|
#include "gxdevice.h"
|
||||||
#include "gsstate.h"
|
#include "gsstate.h"
|
||||||
|
@ -312,6 +313,12 @@ z2grestoreall(i_ctx_t *i_ctx_p)
|
||||||
private int
|
private int
|
||||||
z2restore(i_ctx_t *i_ctx_p)
|
z2restore(i_ctx_t *i_ctx_p)
|
||||||
{
|
{
|
||||||
|
alloc_save_t *asave;
|
||||||
|
bool saveLockSafety = gs_currentdevice_inline(igs)->LockSafetyParams;
|
||||||
|
int code = restore_check_save(i_ctx_p, &asave);
|
||||||
|
|
||||||
|
if (code < 0) return code;
|
||||||
|
|
||||||
while (gs_state_saved(gs_state_saved(igs))) {
|
while (gs_state_saved(gs_state_saved(igs))) {
|
||||||
if (restore_page_device(igs, gs_state_saved(igs)))
|
if (restore_page_device(igs, gs_state_saved(igs)))
|
||||||
return push_callout(i_ctx_p, "%restore1pagedevice");
|
return push_callout(i_ctx_p, "%restore1pagedevice");
|
||||||
|
@ -319,7 +326,10 @@ z2restore(i_ctx_t *i_ctx_p)
|
||||||
}
|
}
|
||||||
if (restore_page_device(igs, gs_state_saved(igs)))
|
if (restore_page_device(igs, gs_state_saved(igs)))
|
||||||
return push_callout(i_ctx_p, "%restorepagedevice");
|
return push_callout(i_ctx_p, "%restorepagedevice");
|
||||||
return zrestore(i_ctx_p);
|
code = dorestore(i_ctx_p, asave);
|
||||||
|
if (code < 0)
|
||||||
|
gs_currentdevice_inline(igs)->LockSafetyParams = saveLockSafety;
|
||||||
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* <gstate> setgstate - */
|
/* <gstate> setgstate - */
|
||||||
|
|
|
@ -102,35 +102,52 @@ zsave(i_ctx_t *i_ctx_p)
|
||||||
private int restore_check_operand(os_ptr, alloc_save_t **, gs_dual_memory_t *);
|
private int restore_check_operand(os_ptr, alloc_save_t **, gs_dual_memory_t *);
|
||||||
private int restore_check_stack(const ref_stack_t *, const alloc_save_t *, bool);
|
private int restore_check_stack(const ref_stack_t *, const alloc_save_t *, bool);
|
||||||
private void restore_fix_stack(ref_stack_t *, const alloc_save_t *, bool);
|
private void restore_fix_stack(ref_stack_t *, const alloc_save_t *, bool);
|
||||||
|
|
||||||
int
|
int
|
||||||
zrestore(i_ctx_t *i_ctx_p)
|
restore_check_save(i_ctx_t *i_ctx_p, alloc_save_t **asave)
|
||||||
{
|
{
|
||||||
os_ptr op = osp;
|
os_ptr op = osp;
|
||||||
alloc_save_t *asave;
|
int code = restore_check_operand(op, asave, idmemory);
|
||||||
bool last;
|
|
||||||
vm_save_t *vmsave;
|
|
||||||
int code = restore_check_operand(op, &asave, idmemory);
|
|
||||||
|
|
||||||
if (code < 0)
|
if (code < 0)
|
||||||
return code;
|
return code;
|
||||||
if_debug2('u', "[u]vmrestore 0x%lx, id = %lu\n",
|
if_debug2('u', "[u]vmrestore 0x%lx, id = %lu\n",
|
||||||
(ulong) alloc_save_client_data(asave),
|
(ulong) alloc_save_client_data(*asave),
|
||||||
(ulong) op->value.saveid);
|
(ulong) op->value.saveid);
|
||||||
if (I_VALIDATE_BEFORE_RESTORE)
|
if (I_VALIDATE_BEFORE_RESTORE)
|
||||||
ivalidate_clean_spaces(i_ctx_p);
|
ivalidate_clean_spaces(i_ctx_p);
|
||||||
/* Check the contents of the stacks. */
|
/* Check the contents of the stacks. */
|
||||||
osp--;
|
osp--;
|
||||||
{
|
if ((code = restore_check_stack(&o_stack, *asave, false)) < 0 ||
|
||||||
int code;
|
(code = restore_check_stack(&e_stack, *asave, true)) < 0 ||
|
||||||
|
(code = restore_check_stack(&d_stack, *asave, false)) < 0
|
||||||
if ((code = restore_check_stack(&o_stack, asave, false)) < 0 ||
|
|
||||||
(code = restore_check_stack(&e_stack, asave, true)) < 0 ||
|
|
||||||
(code = restore_check_stack(&d_stack, asave, false)) < 0
|
|
||||||
) {
|
) {
|
||||||
osp++;
|
osp++;
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
osp++;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* the emantics of restore differ slightly between Level 1 and
|
||||||
|
* Level 2 and later - the latter inclues restoring the device
|
||||||
|
* state (whilst Level 1 didn't have "page devices" as such).
|
||||||
|
* Hence we have two restore operators - one here (Level 1)
|
||||||
|
* and one in zdevice2.c (Level 2+). For that reason, the
|
||||||
|
* operand checking and guts of the restore operation are
|
||||||
|
* separated so both implementations can use them to best
|
||||||
|
* effect.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
dorestore(i_ctx_t *i_ctx_p, alloc_save_t *asave)
|
||||||
|
{
|
||||||
|
os_ptr op = osp;
|
||||||
|
bool last;
|
||||||
|
vm_save_t *vmsave;
|
||||||
|
int code;
|
||||||
|
|
||||||
|
osp--;
|
||||||
|
|
||||||
/* Reset l_new in all stack entries if the new save level is zero. */
|
/* Reset l_new in all stack entries if the new save level is zero. */
|
||||||
/* Also do some special fixing on the e-stack. */
|
/* Also do some special fixing on the e-stack. */
|
||||||
restore_fix_stack(&o_stack, asave, false);
|
restore_fix_stack(&o_stack, asave, false);
|
||||||
|
@ -170,9 +187,23 @@ zrestore(i_ctx_t *i_ctx_p)
|
||||||
/* cause an 'invalidaccess' in setuserparams. Temporarily set */
|
/* cause an 'invalidaccess' in setuserparams. Temporarily set */
|
||||||
/* LockFilePermissions false until the gs_lev2.ps can do a */
|
/* LockFilePermissions false until the gs_lev2.ps can do a */
|
||||||
/* setuserparams from the restored userparam dictionary. */
|
/* setuserparams from the restored userparam dictionary. */
|
||||||
|
/* NOTE: This is safe to do here, since the restore has */
|
||||||
|
/* successfully completed - this should never come before any */
|
||||||
|
/* operation that can trigger an error */
|
||||||
i_ctx_p->LockFilePermissions = false;
|
i_ctx_p->LockFilePermissions = false;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
zrestore(i_ctx_t *i_ctx_p)
|
||||||
|
{
|
||||||
|
alloc_save_t *asave;
|
||||||
|
int code = restore_check_save(i_ctx_p, &asave);
|
||||||
|
if (code < 0)
|
||||||
|
return code;
|
||||||
|
return dorestore(i_ctx_p, asave);
|
||||||
|
}
|
||||||
|
|
||||||
/* Check the operand of a restore. */
|
/* Check the operand of a restore. */
|
||||||
private int
|
private int
|
||||||
restore_check_operand(os_ptr op, alloc_save_t ** pasave,
|
restore_check_operand(os_ptr op, alloc_save_t ** pasave,
|
||||||
|
|
Loading…
Reference in a new issue