changelog shortlog tags branches files raw gz bz2 help

Mercurial > hg > plan9front / changeset: gs: apply fixes for CVE-2018-16509 (thanks jsmoody)

changeset 7253: 986e26228cfe
parent 7252: 523d2d3e473f
child 7254: 03b53375c4f5
author: cinap_lenrek@felloff.net
date: Thu, 23 May 2019 14:59:28 +0200
files: sys/lib/ghostscript/gs_init.ps sys/src/cmd/gs/lib/gs_init.ps sys/src/cmd/gs/src/gsdevice.c sys/src/cmd/gs/src/isave.h sys/src/cmd/gs/src/zdevice2.c sys/src/cmd/gs/src/zvmem.c
description: gs: apply fixes for CVE-2018-16509 (thanks jsmoody)
     1.1--- a/sys/lib/ghostscript/gs_init.ps
     1.2+++ b/sys/lib/ghostscript/gs_init.ps
     1.3@@ -1992,6 +1992,17 @@ readonly def
     1.4 % If we are running in SAFER mode, lock things down
     1.5 SAFER { .setsafe } if
     1.6 
     1.7+/UndefinePostScriptOperators {
     1.8+  [
     1.9+  /condition /currentcontext /detach /.fork /join /.localfork /lock /monitor /notify
    1.10+  /wait /yield /.currentscreenphase /.setscreenphase /.image2 /eoviewclip /initviewclip
    1.11+  /viewclip /viewclippath /defineusername
    1.12+  /currentalpha /setalpha /.alphaimage /composite /compositerect /dissolve /sizeimagebox /.sizeimageparams
    1.13+  ]
    1.14+  {systemdict exch .forceundef} forall
    1.15+  //systemdict /UndefinePostScriptOperators .forceundef
    1.16+} bind def
    1.17+
    1.18 % If we delayed binding, make it possible to do it later.
    1.19 /.bindnow {
    1.20   currentuserparams /IdiomRecognition .knownget {
    1.21@@ -2005,6 +2016,7 @@ SAFER { .setsafe } if
    1.22   //systemdict /.delaybind {} .forceput	% reclaim the space
    1.23   //systemdict /.bindnow .forceundef	% ditto
    1.24   put
    1.25+  //systemdict /UndefinePostScriptOperators get exec
    1.26   //systemdict /.forcedef .forceundef		% remove temptation
    1.27   //systemdict /.forceput .forceundef		% ditto
    1.28   //systemdict /.forceundef .forceundef		% ditto
     2.1--- a/sys/src/cmd/gs/lib/gs_init.ps
     2.2+++ b/sys/src/cmd/gs/lib/gs_init.ps
     2.3@@ -1992,6 +1992,17 @@ readonly def
     2.4 % If we are running in SAFER mode, lock things down
     2.5 SAFER { .setsafe } if
     2.6 
     2.7+/UndefinePostScriptOperators {
     2.8+  [
     2.9+  /condition /currentcontext /detach /.fork /join /.localfork /lock /monitor /notify
    2.10+  /wait /yield /.currentscreenphase /.setscreenphase /.image2 /eoviewclip /initviewclip
    2.11+  /viewclip /viewclippath /defineusername
    2.12+  /currentalpha /setalpha /.alphaimage /composite /compositerect /dissolve /sizeimagebox /.sizeimageparams
    2.13+  ]
    2.14+  {systemdict exch .forceundef} forall
    2.15+  //systemdict /UndefinePostScriptOperators .forceundef
    2.16+} bind def
    2.17+
    2.18 % If we delayed binding, make it possible to do it later.
    2.19 /.bindnow {
    2.20   currentuserparams /IdiomRecognition .knownget {
    2.21@@ -2005,6 +2016,7 @@ SAFER { .setsafe } if
    2.22   //systemdict /.delaybind {} .forceput	% reclaim the space
    2.23   //systemdict /.bindnow .forceundef	% ditto
    2.24   put
    2.25+  //systemdict /UndefinePostScriptOperators get exec
    2.26   //systemdict /.forcedef .forceundef		% remove temptation
    2.27   //systemdict /.forceput .forceundef		% ditto
    2.28   //systemdict /.forceundef .forceundef		% ditto
     3.1--- a/sys/src/cmd/gs/src/gsdevice.c
     3.2+++ b/sys/src/cmd/gs/src/gsdevice.c
     3.3@@ -480,21 +480,30 @@ gx_device_retain(gx_device *dev, bool re
     3.4 int
     3.5 gs_nulldevice(gs_state * pgs)
     3.6 {
     3.7+    int code = 0;
     3.8+    int saveLockSafety = false;
     3.9+
    3.10     if (pgs->device == 0 || !gx_device_is_null(pgs->device)) {
    3.11-	gx_device *ndev;
    3.12-	int code = gs_copydevice(&ndev, (const gx_device *)&gs_null_device,
    3.13-				 pgs->memory);
    3.14-
    3.15+        gx_device *ndev;
    3.16+        code = gs_copydevice(&ndev, (const gx_device *)&gs_null_device, pgs->memory);
    3.17 	if (code < 0)
    3.18 	    return code;
    3.19+        if (gs_currentdevice_inline(pgs) != NULL)
    3.20+            saveLockSafety = gs_currentdevice_inline(pgs)->LockSafetyParams;
    3.21+
    3.22 	/*
    3.23 	 * Internal devices have a reference count of 0, not 1,
    3.24 	 * aside from references from graphics states.
    3.25 	 */
    3.26 	rc_init(ndev, pgs->memory, 0);
    3.27-	return gs_setdevice_no_erase(pgs, ndev);
    3.28+        code = gs_setdevice_no_erase(pgs, ndev);
    3.29+        if (code < 0) {
    3.30+            gs_free_object(pgs->memory, ndev, "gs_copydevice(device)");
    3.31+            return code;
    3.32+        }
    3.33+        gs_currentdevice_inline(pgs)->LockSafetyParams = saveLockSafety;
    3.34     }
    3.35-    return 0;
    3.36+    return code;
    3.37 }
    3.38 
    3.39 /* Close a device.  The client is responsible for ensuring that */
     4.1--- a/sys/src/cmd/gs/src/isave.h
     4.2+++ b/sys/src/cmd/gs/src/isave.h
     4.3@@ -116,4 +116,8 @@ void alloc_set_not_in_save(gs_dual_memor
     4.4 /* Remove entries from font and character caches. */
     4.5 void font_restore(const alloc_save_t * save);
     4.6 
     4.7+int restore_check_save(i_ctx_t *i_ctx_p, alloc_save_t **asave);
     4.8+
     4.9+int dorestore(i_ctx_t *i_ctx_p, alloc_save_t *asave);
    4.10+
    4.11 #endif /* isave_INCLUDED */
     5.1--- a/sys/src/cmd/gs/src/zdevice2.c
     5.2+++ b/sys/src/cmd/gs/src/zdevice2.c
     5.3@@ -27,6 +27,7 @@
     5.4 #include "igstate.h"
     5.5 #include "iname.h"
     5.6 #include "iutil.h"
     5.7+#include "isave.h"
     5.8 #include "store.h"
     5.9 #include "gxdevice.h"
    5.10 #include "gsstate.h"
    5.11@@ -312,6 +313,12 @@ z2grestoreall(i_ctx_t *i_ctx_p)
    5.12 private int
    5.13 z2restore(i_ctx_t *i_ctx_p)
    5.14 {
    5.15+    alloc_save_t *asave;
    5.16+    bool saveLockSafety = gs_currentdevice_inline(igs)->LockSafetyParams;
    5.17+    int code = restore_check_save(i_ctx_p, &asave);
    5.18+
    5.19+    if (code < 0) return code;
    5.20+
    5.21     while (gs_state_saved(gs_state_saved(igs))) {
    5.22 	if (restore_page_device(igs, gs_state_saved(igs)))
    5.23 	    return push_callout(i_ctx_p, "%restore1pagedevice");
    5.24@@ -319,7 +326,10 @@ z2restore(i_ctx_t *i_ctx_p)
    5.25     }
    5.26     if (restore_page_device(igs, gs_state_saved(igs)))
    5.27 	return push_callout(i_ctx_p, "%restorepagedevice");
    5.28-    return zrestore(i_ctx_p);
    5.29+    code = dorestore(i_ctx_p, asave);
    5.30+    if (code < 0)
    5.31+        gs_currentdevice_inline(igs)->LockSafetyParams = saveLockSafety;
    5.32+    return code;
    5.33 }
    5.34 
    5.35 /* <gstate> setgstate - */
     6.1--- a/sys/src/cmd/gs/src/zvmem.c
     6.2+++ b/sys/src/cmd/gs/src/zvmem.c
     6.3@@ -102,35 +102,52 @@ zsave(i_ctx_t *i_ctx_p)
     6.4 private int restore_check_operand(os_ptr, alloc_save_t **, gs_dual_memory_t *);
     6.5 private int restore_check_stack(const ref_stack_t *, const alloc_save_t *, bool);
     6.6 private void restore_fix_stack(ref_stack_t *, const alloc_save_t *, bool);
     6.7+
     6.8 int
     6.9-zrestore(i_ctx_t *i_ctx_p)
    6.10+restore_check_save(i_ctx_t *i_ctx_p, alloc_save_t **asave)
    6.11 {
    6.12     os_ptr op = osp;
    6.13-    alloc_save_t *asave;
    6.14-    bool last;
    6.15-    vm_save_t *vmsave;
    6.16-    int code = restore_check_operand(op, &asave, idmemory);
    6.17-
    6.18+    int code = restore_check_operand(op, asave, idmemory);
    6.19     if (code < 0)
    6.20 	return code;
    6.21     if_debug2('u', "[u]vmrestore 0x%lx, id = %lu\n",
    6.22-	      (ulong) alloc_save_client_data(asave),
    6.23+	      (ulong) alloc_save_client_data(*asave),
    6.24 	      (ulong) op->value.saveid);
    6.25     if (I_VALIDATE_BEFORE_RESTORE)
    6.26 	ivalidate_clean_spaces(i_ctx_p);
    6.27     /* Check the contents of the stacks. */
    6.28     osp--;
    6.29-    {
    6.30-	int code;
    6.31+    if ((code = restore_check_stack(&o_stack, *asave, false)) < 0 ||
    6.32+        (code = restore_check_stack(&e_stack, *asave, true)) < 0 ||
    6.33+        (code = restore_check_stack(&d_stack, *asave, false)) < 0
    6.34+        ) {
    6.35+        osp++;
    6.36+        return code;
    6.37+    }
    6.38+    osp++;
    6.39+    return 0;
    6.40+}
    6.41 
    6.42-	if ((code = restore_check_stack(&o_stack, asave, false)) < 0 ||
    6.43-	    (code = restore_check_stack(&e_stack, asave, true)) < 0 ||
    6.44-	    (code = restore_check_stack(&d_stack, asave, false)) < 0
    6.45-	    ) {
    6.46-	    osp++;
    6.47-	    return code;
    6.48-	}
    6.49-    }
    6.50+/*
    6.51+ * the emantics of restore differ slightly between Level 1 and
    6.52+ * Level 2 and later - the latter inclues restoring the device
    6.53+ * state (whilst Level 1 didn't have "page devices" as such).
    6.54+ * Hence we have two restore operators - one here (Level 1)
    6.55+ * and one in zdevice2.c (Level 2+). For that reason, the
    6.56+ * operand checking and guts of the restore operation are
    6.57+ * separated so both implementations can use them to best
    6.58+ * effect.
    6.59+ */
    6.60+int
    6.61+dorestore(i_ctx_t *i_ctx_p, alloc_save_t *asave)
    6.62+{
    6.63+    os_ptr op = osp;
    6.64+    bool last;
    6.65+    vm_save_t *vmsave;
    6.66+    int code;
    6.67+
    6.68+    osp--;
    6.69+
    6.70     /* Reset l_new in all stack entries if the new save level is zero. */
    6.71     /* Also do some special fixing on the e-stack. */
    6.72     restore_fix_stack(&o_stack, asave, false);
    6.73@@ -170,9 +187,23 @@ zrestore(i_ctx_t *i_ctx_p)
    6.74     /* cause an 'invalidaccess' in setuserparams. Temporarily set     */
    6.75     /* LockFilePermissions false until the gs_lev2.ps can do a        */
    6.76     /* setuserparams from the restored userparam dictionary.          */
    6.77+    /* NOTE: This is safe to do here, since the restore has           */
    6.78+    /* successfully completed - this should never come before any     */
    6.79+    /* operation that can trigger an error                            */
    6.80     i_ctx_p->LockFilePermissions = false;
    6.81     return 0;
    6.82 }
    6.83+
    6.84+int
    6.85+zrestore(i_ctx_t *i_ctx_p)
    6.86+{
    6.87+    alloc_save_t *asave;
    6.88+    int code = restore_check_save(i_ctx_p, &asave);
    6.89+    if (code < 0)
    6.90+        return code;
    6.91+    return dorestore(i_ctx_p, asave);
    6.92+}
    6.93+
    6.94 /* Check the operand of a restore. */
    6.95 private int
    6.96 restore_check_operand(os_ptr op, alloc_save_t ** pasave,