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
|
||||
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.
|
||||
/.bindnow {
|
||||
currentuserparams /IdiomRecognition .knownget {
|
||||
|
@ -2005,6 +2016,7 @@ SAFER { .setsafe } if
|
|||
//systemdict /.delaybind {} .forceput % reclaim the space
|
||||
//systemdict /.bindnow .forceundef % ditto
|
||||
put
|
||||
//systemdict /UndefinePostScriptOperators get exec
|
||||
//systemdict /.forcedef .forceundef % remove temptation
|
||||
//systemdict /.forceput .forceundef % ditto
|
||||
//systemdict /.forceundef .forceundef % ditto
|
||||
|
|
|
@ -1992,6 +1992,17 @@ readonly def
|
|||
% If we are running in SAFER mode, lock things down
|
||||
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.
|
||||
/.bindnow {
|
||||
currentuserparams /IdiomRecognition .knownget {
|
||||
|
@ -2005,6 +2016,7 @@ SAFER { .setsafe } if
|
|||
//systemdict /.delaybind {} .forceput % reclaim the space
|
||||
//systemdict /.bindnow .forceundef % ditto
|
||||
put
|
||||
//systemdict /UndefinePostScriptOperators get exec
|
||||
//systemdict /.forcedef .forceundef % remove temptation
|
||||
//systemdict /.forceput .forceundef % ditto
|
||||
//systemdict /.forceundef .forceundef % ditto
|
||||
|
|
|
@ -480,21 +480,30 @@ gx_device_retain(gx_device *dev, bool retained)
|
|||
int
|
||||
gs_nulldevice(gs_state * pgs)
|
||||
{
|
||||
if (pgs->device == 0 || !gx_device_is_null(pgs->device)) {
|
||||
gx_device *ndev;
|
||||
int code = gs_copydevice(&ndev, (const gx_device *)&gs_null_device,
|
||||
pgs->memory);
|
||||
int code = 0;
|
||||
int saveLockSafety = false;
|
||||
|
||||
if (pgs->device == 0 || !gx_device_is_null(pgs->device)) {
|
||||
gx_device *ndev;
|
||||
code = gs_copydevice(&ndev, (const gx_device *)&gs_null_device, pgs->memory);
|
||||
if (code < 0)
|
||||
return code;
|
||||
if (gs_currentdevice_inline(pgs) != NULL)
|
||||
saveLockSafety = gs_currentdevice_inline(pgs)->LockSafetyParams;
|
||||
|
||||
/*
|
||||
* Internal devices have a reference count of 0, not 1,
|
||||
* aside from references from graphics states.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
gs_currentdevice_inline(pgs)->LockSafetyParams = saveLockSafety;
|
||||
}
|
||||
return 0;
|
||||
return code;
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
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 */
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "igstate.h"
|
||||
#include "iname.h"
|
||||
#include "iutil.h"
|
||||
#include "isave.h"
|
||||
#include "store.h"
|
||||
#include "gxdevice.h"
|
||||
#include "gsstate.h"
|
||||
|
@ -312,6 +313,12 @@ z2grestoreall(i_ctx_t *i_ctx_p)
|
|||
private int
|
||||
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))) {
|
||||
if (restore_page_device(igs, gs_state_saved(igs)))
|
||||
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)))
|
||||
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 - */
|
||||
|
|
|
@ -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_stack(const ref_stack_t *, const alloc_save_t *, bool);
|
||||
private void restore_fix_stack(ref_stack_t *, const alloc_save_t *, bool);
|
||||
|
||||
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;
|
||||
alloc_save_t *asave;
|
||||
bool last;
|
||||
vm_save_t *vmsave;
|
||||
int code = restore_check_operand(op, &asave, idmemory);
|
||||
|
||||
int code = restore_check_operand(op, asave, idmemory);
|
||||
if (code < 0)
|
||||
return code;
|
||||
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);
|
||||
if (I_VALIDATE_BEFORE_RESTORE)
|
||||
ivalidate_clean_spaces(i_ctx_p);
|
||||
/* Check the contents of the stacks. */
|
||||
osp--;
|
||||
{
|
||||
int code;
|
||||
|
||||
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++;
|
||||
return code;
|
||||
}
|
||||
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++;
|
||||
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. */
|
||||
/* Also do some special fixing on the e-stack. */
|
||||
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 */
|
||||
/* LockFilePermissions false until the gs_lev2.ps can do a */
|
||||
/* 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;
|
||||
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. */
|
||||
private int
|
||||
restore_check_operand(os_ptr op, alloc_save_t ** pasave,
|
||||
|
|
Loading…
Reference in a new issue