ref: e55778d67e8fb4ac0756420b3e52abb1ac02b9f8
parent: 197ff3ac2f4fe9be7eefc9c8409cee04e267b04a
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Thu May 23 10:59:28 EDT 2019
gs: apply fixes for CVE-2018-16509 (thanks jsmoody)
--- a/sys/lib/ghostscript/gs_init.ps
+++ b/sys/lib/ghostscript/gs_init.ps
@@ -1992,6 +1992,17 @@
% 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 @@
//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
--- a/sys/src/cmd/gs/lib/gs_init.ps
+++ b/sys/src/cmd/gs/lib/gs_init.ps
@@ -1992,6 +1992,17 @@
% 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 @@
//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
--- a/sys/src/cmd/gs/src/gsdevice.c
+++ b/sys/src/cmd/gs/src/gsdevice.c
@@ -480,21 +480,30 @@
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 */
--- a/sys/src/cmd/gs/src/isave.h
+++ b/sys/src/cmd/gs/src/isave.h
@@ -116,4 +116,8 @@
/* 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 */
--- a/sys/src/cmd/gs/src/zdevice2.c
+++ b/sys/src/cmd/gs/src/zdevice2.c
@@ -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 @@
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 @@
}
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 - */
--- a/sys/src/cmd/gs/src/zvmem.c
+++ b/sys/src/cmd/gs/src/zvmem.c
@@ -102,35 +102,52 @@
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 @@
/* 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,