gs: apply fixes for CVE-2018-16509 (thanks jsmoody)

This commit is contained in:
cinap_lenrek 2019-05-23 14:59:28 +02:00
parent 197ff3ac2f
commit e55778d67e
6 changed files with 102 additions and 24 deletions

View file

@ -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

View file

@ -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

View file

@ -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 */

View file

@ -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 */

View file

@ -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 - */

View file

@ -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,