ports/opt (3.4): [notify] ghostscript: security fix, several -dSAFER sandbox bypass vulnerabilities

crux at crux.nu crux at crux.nu
Sat Aug 25 18:08:13 UTC 2018


commit 11f86218d26b42b30824d7678ec4a7b54cbd50e9
Author: Juergen Daubert <jue at jue.li>
Date:   Sat Aug 25 20:05:46 2018 +0200

    [notify] ghostscript: security fix, several -dSAFER sandbox bypass vulnerabilities
    
    See
    - https://www.kb.cert.org/vuls/id/332928
    - http://seclists.org/oss-sec/2018/q3/142

diff --git a/ghostscript/.signature b/ghostscript/.signature
index 8c0b3ca66..30d34089a 100644
--- a/ghostscript/.signature
+++ b/ghostscript/.signature
@@ -1,6 +1,19 @@
 untrusted comment: verify with /etc/ports/opt.pub
-RWSE3ohX2g5d/fAfjoz0I76mLUiRieNsO8V6jhq5EVQ6xW14I/nmfV+aCRN4GXNPzuibAVddAgeDFQHT67ET7EstLrX9oiWLqgg=
-SHA256 (Pkgfile) = bf1af24031803ccccd487cd7dfed24ead00597c00daef0f3c1698ee0b5d46f71
+RWSE3ohX2g5d/froAVb0xfR6peImTLVw25laSQoDWaxYCxl8iIc3+eGFpv01RYYqliddT0nIm31YTdVwZS/RF2l9f/HkZo2LKg4=
+SHA256 (Pkgfile) = e4a88a0f36aec4197fc95a307812e31bd329eb53d64dbf81825cfa65fa09b778
 SHA256 (.footprint) = 3514d4810f8fe93de5e8d03bc500e39d81dc6ab4118d0728c50d1e50e3bbc606
 SHA256 (ghostscript-9.23.tar.xz) = 1fcedc27d4d6081105cdf35606cb3f809523423a6cf9e3c23cead3525d6ae8d9
 SHA256 (ghostscript-fonts-std-8.11.tar.gz) = 0eb6f356119f2e49b2563210852e17f57f9dcc5755f350a69a46a0d641a0c401
+SHA256 (ghostpdl.git-0b6cd191.patch) = 562502dd1eccce30010aa2f00805132dfef86aa3675fb1df6fd00cbca8a4d786
+SHA256 (ghostpdl.git-b575e1ec.patch) = 09bf11a0dd2ca575df16e8d08ef64f7d195f8be9fe050026b5ce5d27cfcd8af9
+SHA256 (ghostpdl.git-8e9ce501.patch) = dc73b4592a862bbab7d8a4d326503d802ba4266940574ad2d73a444c977953f9
+SHA256 (ghostpdl.git-241d9111.patch) = 7f6fc634cf228c12b12c93514c419d7d6f7daad49fcd86baa23a7ff3b7fb55a4
+SHA256 (ghostpdl.git-c432131c.patch) = 12122123e1df839d39f844223a24e76a18ea0aab05cfa0012f7b2590792ca8ea
+SHA256 (ghostpdl.git-e01e77a3.patch) = 4061b542ad640298caa595c02bcc3b095e6f5682996c4b7330c6a36c04f19a94
+SHA256 (ghostpdl.git-0edd3d6c.patch) = 90be1bd4374d2af5b4675275030b7c528a3a03dfb0c4980337c5eec920326d4b
+SHA256 (ghostpdl.git-a054156d.patch) = 0f9b55466f45b404a4ccb9fcb18e203762eb06aa5c1b95bc7a2c8480601952c3
+SHA256 (ghostpdl.git-0d390118.patch) = 7ea332e7b2059c1f094f94714bc6b4eaf0de2515ae70b469ecfe96e7ccaf7317
+SHA256 (ghostpdl.git-c3476dde.patch) = 4ed94469231187ce2a512b4784f6fc7238543cf39b2625e2c09357fefed8aa18
+SHA256 (ghostpdl.git-b326a716.patch) = 6529a57c842e9a1573826bc6553956303297b7723c14f2bfcaeb1d899ec65c26
+SHA256 (ghostpdl.git-78911a01.patch) = 128065c4120cebcc9f177ce9ca2a525e240fd97a07727767210880080e87f507
+SHA256 (ghostpdl.git-5516c614.patch) = 125d5ffd5e891aa42aecb44025126130d014c8e8e98feca0fb6aab17cfe7908c
diff --git a/ghostscript/Pkgfile b/ghostscript/Pkgfile
index 7188478be..518daca8f 100644
--- a/ghostscript/Pkgfile
+++ b/ghostscript/Pkgfile
@@ -5,12 +5,39 @@
 
 name=ghostscript
 version=9.23
-release=1
+release=2
 source=(https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs${version/./}/$name-$version.tar.xz
-        http://downloads.sourceforge.net/sourceforge/gs-fonts/$name-fonts-std-8.11.tar.gz)
+        http://downloads.sourceforge.net/sourceforge/gs-fonts/$name-fonts-std-8.11.tar.gz
+        ghostpdl.git-0b6cd191.patch
+        ghostpdl.git-b575e1ec.patch
+        ghostpdl.git-8e9ce501.patch
+        ghostpdl.git-241d9111.patch
+        ghostpdl.git-c432131c.patch
+        ghostpdl.git-e01e77a3.patch
+        ghostpdl.git-0edd3d6c.patch
+        ghostpdl.git-a054156d.patch
+        ghostpdl.git-0d390118.patch
+        ghostpdl.git-c3476dde.patch
+        ghostpdl.git-b326a716.patch
+        ghostpdl.git-78911a01.patch
+        ghostpdl.git-5516c614.patch)
 
 build () {
     cd $name-$version
+ 
+    patch -p1 -i $SRC/ghostpdl.git-0b6cd191.patch
+    patch -p1 -i $SRC/ghostpdl.git-b575e1ec.patch
+    patch -p1 -i $SRC/ghostpdl.git-8e9ce501.patch
+    patch -p1 -i $SRC/ghostpdl.git-241d9111.patch
+    patch -p1 -i $SRC/ghostpdl.git-c432131c.patch
+    patch -p1 -i $SRC/ghostpdl.git-e01e77a3.patch
+    patch -p1 -i $SRC/ghostpdl.git-0edd3d6c.patch
+    patch -p1 -i $SRC/ghostpdl.git-a054156d.patch
+    patch -p1 -i $SRC/ghostpdl.git-0d390118.patch
+    patch -p1 -i $SRC/ghostpdl.git-c3476dde.patch
+    patch -p1 -i $SRC/ghostpdl.git-b326a716.patch
+    patch -p1 -i $SRC/ghostpdl.git-78911a01.patch
+    patch -p1 -i $SRC/ghostpdl.git-5516c614.patch
 
     ./configure --prefix=/usr \
                 --enable-cups \
diff --git a/ghostscript/ghostpdl.git-0b6cd191.patch b/ghostscript/ghostpdl.git-0b6cd191.patch
new file mode 100644
index 000000000..5c7323528
--- /dev/null
+++ b/ghostscript/ghostpdl.git-0b6cd191.patch
@@ -0,0 +1,86 @@
+From 0b6cd1918e1ec4ffd087400a754a845180a4522b Mon Sep 17 00:00:00 2001
+From: Ken Sharp <ken.sharp at artifex.com>
+Date: Thu, 23 Aug 2018 14:12:48 +0100
+Subject: [PATCH] Fix Bug 699660 "shading_param incomplete type checking"
+
+Its possible to pass a t_struct parameter to .shfill which is not a
+shading function built by .buildshading. This could then lead to memory
+corruption or a segmentation fault by treating the object passed in
+as if it were a shading.
+
+Its non-trivial to check the t_struct, because this function can take
+7 different kinds of structures as a parameter. Checking these is
+possible, of course, but would add a performance penalty.
+
+However, we can note that we never call .shfill without first calling
+.buildshading, and we never call .buildshading without immediately
+calling .shfill. So we can treat these as an atomic operation. The
+.buildshading function takes all its parameters as PostScript objects
+and validates them, so that should be safe.
+
+This allows us to 'hide' the .shfill operator preventing the possibility
+of passing an invalid parameter.
+---
+ Resource/Init/gs_init.ps  | 4 ++--
+ Resource/Init/gs_ll3.ps   | 7 ++++++-
+ Resource/Init/pdf_draw.ps | 3 +--
+ 3 files changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
+index 5a5a428..bc17d42 100644
+--- a/Resource/Init/gs_init.ps
++++ b/Resource/Init/gs_init.ps
+@@ -2196,8 +2196,8 @@ SAFER { .setsafeglobal } if
+ /.getiodevice /.getdevparms /.putdevparams /.bbox_transform /.matchmedia /.matchpagesize /.defaultpapersize
+ /.oserrno /.setoserrno /.oserrorstring /.getCPSImode
+ /.getscanconverter /.setscanconverter /.type1encrypt /.type1decrypt/.languagelevel /.setlanguagelevel /.eqproc /.fillpage /.buildpattern1 /.saslprep
+-/.buildshading1 /.buildshadin2 /.buildshading3 /.buildshading4 /.buildshading5 /.buildshading6 /.buildshading7 /.buildshadingpattern
+-/.argindex /.bytestring /.namestring /.stringbreak /.stringmatch /.globalvmarray /.globalvmdict /.globalvmpackedarray /.globalvmstring
++/.buildshading1 /.buildshading2 /.buildshading3 /.buildshading4 /.buildshading5 /.buildshading6 /.buildshading7 /.buildshadingpattern
++%/.shfill /.argindex /.bytestring /.namestring /.stringbreak /.stringmatch /.globalvmarray /.globalvmdict /.globalvmpackedarray /.globalvmstring
+ /.localvmarray /.localvmdict /.localvmpackedarray /.localvmstring /.systemvmarray /.systemvmdict /.systemvmpackedarray /.systemvmstring /.systemvmfile /.systemvmlibfile
+ /.systemvmSFD /.settrapparams /.currentsystemparams /.currentuserparams /.getsystemparam /.getuserparam /.setsystemparams /.setuserparams
+ /.checkpassword /.locale_to_utf8 /.currentglobal /.gcheck /.imagepath
+diff --git a/Resource/Init/gs_ll3.ps b/Resource/Init/gs_ll3.ps
+index 5aa56a3..1d37e53 100644
+--- a/Resource/Init/gs_ll3.ps
++++ b/Resource/Init/gs_ll3.ps
+@@ -440,6 +440,11 @@ systemdict /.reuseparamdict mark
+     /shfill .systemvar /undefined signalerror
+   } ifelse
+ } bind def
++
++/.buildshading_and_shfill {
++  .buildshading .shfill
++} bind def
++
+ systemdict /.reuseparamdict undef
+ 
+ /.buildpattern2 {	% <template> <matrix> .buildpattern2
+@@ -464,7 +469,7 @@ systemdict /.reuseparamdict undef
+         % Currently, .shfill requires that the color space
+         % in the pattern be the current color space.
+         % Disable overprintmode for shfill
+-  { dup gsave 0 .setoverprintmode .buildshading .shfill } stopped
++  { dup gsave 0 .setoverprintmode .buildshading_and_shfill } stopped
+   grestore {
+     /$error .systemvar /errorinfo 2 copy known {
+       pop pop
+diff --git a/Resource/Init/pdf_draw.ps b/Resource/Init/pdf_draw.ps
+index b3d94ac..aef249d 100644
+--- a/Resource/Init/pdf_draw.ps
++++ b/Resource/Init/pdf_draw.ps
+@@ -1365,9 +1365,8 @@ drawopdict begin
+     { dup /.shading .knownget {
+         exch pop
+       } {
+-       .buildshading
++       .buildshading_and_shfill
+       } ifelse
+-      .shfill
+     } stopped {
+       pop
+       (   **** Error: Ignoring invalid smooth shading object, output may be incorrect.\n)
+-- 
+2.9.1
+
diff --git a/ghostscript/ghostpdl.git-0d390118.patch b/ghostscript/ghostpdl.git-0d390118.patch
new file mode 100644
index 000000000..bcaac484a
--- /dev/null
+++ b/ghostscript/ghostpdl.git-0d390118.patch
@@ -0,0 +1,46 @@
+From: Chris Liddell <chris.liddell at artifex.com>
+Date: Tue, 21 Aug 2018 19:17:05 +0000 (+0100)
+Subject: Bug 699657: properly apply file permissions to .tempfile
+X-Git-Url: http://git.ghostscript.com/?p=ghostpdl.git;a=commitdiff_plain;h=0d390118
+
+Bug 699657: properly apply file permissions to .tempfile
+---
+
+diff --git a/psi/zfile.c b/psi/zfile.c
+index a0acd5a..19996b0 100644
+--- a/psi/zfile.c
++++ b/psi/zfile.c
+@@ -134,7 +134,7 @@ check_file_permissions_reduced(i_ctx_t *i_ctx_p, const char *fname, int len,
+     /* we're protecting arbitrary file system accesses, not Postscript device accesses.
+      * Although, note that %pipe% is explicitly checked for and disallowed elsewhere
+      */
+-    if (iodev != iodev_default(imemory)) {
++    if (iodev && iodev != iodev_default(imemory)) {
+         return 0;
+     }
+ 
+@@ -734,7 +734,23 @@ ztempfile(i_ctx_t *i_ctx_p)
+     }
+ 
+     if (gp_file_name_is_absolute(pstr, strlen(pstr))) {
+-        if (check_file_permissions(i_ctx_p, pstr, strlen(pstr),
++        int plen = strlen(pstr);
++        const char *sep = gp_file_name_separator();
++#ifdef DEBUG
++        int seplen = strlen(sep);
++        if (seplen != 1)
++            return_error(gs_error_Fatal);
++#endif
++        /* strip off the file name prefix, leave just the directory name
++         * so we can check if we are allowed to write to it
++         */
++        for ( ; plen >=0; plen--) {
++            if (pstr[plen] == sep[0])
++                break;
++        }
++        memcpy(fname, pstr, plen);
++        fname[plen] = '\0';
++        if (check_file_permissions(i_ctx_p, fname, strlen(fname),
+                                    NULL, "PermitFileWriting") < 0) {
+             code = gs_note_error(gs_error_invalidfileaccess);
+             goto done;
diff --git a/ghostscript/ghostpdl.git-0edd3d6c.patch b/ghostscript/ghostpdl.git-0edd3d6c.patch
new file mode 100644
index 000000000..a03193b34
--- /dev/null
+++ b/ghostscript/ghostpdl.git-0edd3d6c.patch
@@ -0,0 +1,21 @@
+From: Chris Liddell <chris.liddell at artifex.com>
+Date: Tue, 21 Aug 2018 19:36:52 +0000 (+0100)
+Subject: Bug 699659: Don't just assume an object is a t_(a)struct
+X-Git-Url: http://git.ghostscript.com/?p=ghostpdl.git;a=commitdiff_plain;h=0edd3d6c
+
+Bug 699659: Don't just assume an object is a t_(a)struct
+---
+
+diff --git a/psi/ztype.c b/psi/ztype.c
+index ad248d9..8307956 100644
+--- a/psi/ztype.c
++++ b/psi/ztype.c
+@@ -76,7 +76,7 @@ ztype(i_ctx_t *i_ctx_p)
+         /* Must be either a stack underflow or a t_[a]struct. */
+         check_op(2);
+         {                       /* Get the type name from the structure. */
+-            if (op[-1].value.pstruct != 0x00) {
++            if ((r_has_type(&op[-1], t_struct) || r_has_type(&op[-1], t_astruct)) && op[-1].value.pstruct != 0x00) {
+             const char *sname =
+                 gs_struct_type_name_string(gs_object_type(imemory,
+                                                           op[-1].value.pstruct));
diff --git a/ghostscript/ghostpdl.git-241d9111.patch b/ghostscript/ghostpdl.git-241d9111.patch
new file mode 100644
index 000000000..7b6f4a4b2
--- /dev/null
+++ b/ghostscript/ghostpdl.git-241d9111.patch
@@ -0,0 +1,43 @@
+From: Chris Liddell <chris.liddell at artifex.com>
+Date: Thu, 23 Aug 2018 14:41:18 +0000 (+0100)
+Subject: Bug 699664: Ensure the correct is in place before cleanup
+X-Git-Url: http://git.ghostscript.com/?p=ghostpdl.git;a=commitdiff_plain;h=241d9111
+
+Bug 699664: Ensure the correct is in place before cleanup
+
+If the PS job replaces the device and leaves that graphics state in place, we
+wouldn't cleanup the default device in the normal way, but rely on the garbage
+collector.
+
+This works (but isn't ideal), *except* when the job replaces the device with
+the null device (using the nulldevice operator) - this means that
+.uninstallpagedevice doesn't replace the existing device with the nulldevice
+(since it is already installed), the device from the graphics ends up being
+freed - and as it is the nulldevice, which we rely on, memory corruption
+and a segfault can happen.
+
+We avoid this by checking if the current device is the nulldevice, and if so,
+restoring it away, before continuing with the device cleanup.
+---
+
+diff --git a/psi/imain.c b/psi/imain.c
+index 2fe1546..138bfc8 100644
+--- a/psi/imain.c
++++ b/psi/imain.c
+@@ -936,6 +936,16 @@ gs_main_finit(gs_main_instance * minst, int exit_status, int code)
+             i_ctx_p = minst->i_ctx_p; /* interp_reclaim could change it. */
+         }
+ 
++        if (i_ctx_p->pgs != NULL && i_ctx_p->pgs->device != NULL &&
++            gx_device_is_null(i_ctx_p->pgs->device)) {
++            /* if the job replaced the device with the nulldevice, we we need to grestore
++               away that device, so the block below can properly dispense
++               with the default device.
++             */
++            int code = gs_grestoreall(i_ctx_p->pgs);
++            if (code < 0) return_error(gs_error_Fatal);
++        }
++
+         if (i_ctx_p->pgs != NULL && i_ctx_p->pgs->device != NULL) {
+             gx_device *pdev = i_ctx_p->pgs->device;
+             const char * dname = pdev->dname;
diff --git a/ghostscript/ghostpdl.git-5516c614.patch b/ghostscript/ghostpdl.git-5516c614.patch
new file mode 100644
index 000000000..5eea5948c
--- /dev/null
+++ b/ghostscript/ghostpdl.git-5516c614.patch
@@ -0,0 +1,230 @@
+From: Chris Liddell <chris.liddell at artifex.com>
+Date: Fri, 24 Aug 2018 08:26:04 +0000 (+0100)
+Subject: Improve restore robustness
+X-Git-Url: http://git.ghostscript.com/?p=ghostpdl.git;a=commitdiff_plain;h=5516c614
+
+Improve restore robustness
+
+Prompted by looking at Bug 699654:
+
+There are two variants of the restore operator in Ghostscript: one is Level 1
+(restoring VM), the other is Level 2+ (adding page device restoring to the
+Level operator).
+
+This was implemented by the Level 2+ version restoring the device in the
+graphics state, then calling the Level 1 implementation to handle actually
+restoring the VM state.
+
+The problem was that the operand checking, and sanity of the save object was
+only done by the Level 1 variant, thus meaning an invalid save object could
+leave a (Level 2+) restore partially complete - with the page device part
+restored, but not VM, and the page device not configured.
+
+To solve that, this commit splits the operand and sanity checking, and the
+core of the restore operation into separate functions, so the relevant
+operators can validate the operand *before* taking any further action. That
+reduces the chances of an invalid restore leaving the interpreter in an
+unknown state.
+
+If an error occurs during the actual VM restore it is essentially fatal, and the
+interpreter cannot continue, but as an extra surety for security, in the event
+of such an error, we'll explicitly preserve the LockSafetyParams of the device,
+rather than rely on the post-restore device configuration (which won't happen
+in the event of an error).
+---
+
+diff --git a/psi/int.mak b/psi/int.mak
+index 1968820..16db0cf 100644
+--- a/psi/int.mak
++++ b/psi/int.mak
+@@ -1086,8 +1086,8 @@ $(PSD)pagedev.dev : $(ECHOGS_XE) $(pagedev_)\
+ 
+ $(PSOBJ)zdevice2.$(OBJ) : $(PSSRC)zdevice2.c $(OP) $(math__h) $(memory__h)\
+  $(dstack_h) $(estack_h)\
+- $(idict_h) $(idparam_h) $(igstate_h) $(iname_h) $(iutil_h) $(store_h)\
+- $(gxdevice_h) $(gsstate_h) $(INT_MAK) $(MAKEDIRS)
++ $(idict_h) $(idparam_h) $(igstate_h) $(iname_h) $(isave) $(iutil_h) \
++ $(store_h) $(gxdevice_h) $(gsstate_h) $(INT_MAK) $(MAKEDIRS)
+ 	$(PSCC) $(PSO_)zdevice2.$(OBJ) $(C_) $(PSSRC)zdevice2.c
+ 
+ $(PSOBJ)zmedia2.$(OBJ) : $(PSSRC)zmedia2.c $(OP) $(math__h) $(memory__h)\
+diff --git a/psi/isave.h b/psi/isave.h
+index 3021639..7eaaced 100644
+--- a/psi/isave.h
++++ b/psi/isave.h
+@@ -128,4 +128,10 @@ int  font_restore(const alloc_save_t * save);
+    express purpose of getting the library context. */
+ gs_memory_t *gs_save_any_memory(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 */
+diff --git a/psi/zdevice2.c b/psi/zdevice2.c
+index 9fbb4e3..0c7080d 100644
+--- a/psi/zdevice2.c
++++ b/psi/zdevice2.c
+@@ -26,6 +26,7 @@
+ #include "igstate.h"
+ #include "iname.h"
+ #include "iutil.h"
++#include "isave.h"
+ #include "store.h"
+ #include "gxdevice.h"
+ #include "gsstate.h"
+@@ -307,13 +308,24 @@ z2grestoreall(i_ctx_t *i_ctx_p)
+     }
+     return 0;
+ }
+-
++/* This is the Level 2+ variant of restore - which adds restoring
++   of the page device to the Level 1 variant in zvmem.c.
++   Previous this restored the device state before calling zrestore.c
++   which validated operands etc, meaning a restore could error out
++   partially complete.
++   The operand checking, and actual VM restore are now in two functions
++   so they can called separately thus, here, we can do as much
++   checking as possible, before embarking on actual changes
++ */
+ /* <save> restore - */
+ static int
+ z2restore(i_ctx_t *i_ctx_p)
+ {
+-    os_ptr op = osp;
+-    check_type(*op, t_save);
++    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_gstate_saved(gs_gstate_saved(igs))) {
+         if (restore_page_device(igs, gs_gstate_saved(igs)))
+@@ -322,7 +334,20 @@ z2restore(i_ctx_t *i_ctx_p)
+     }
+     if (restore_page_device(igs, gs_gstate_saved(igs)))
+         return push_callout(i_ctx_p, "%restorepagedevice");
+-    return zrestore(i_ctx_p);
++
++    code = dorestore(i_ctx_p, asave);
++
++    if (code < 0) {
++        /* An error here is basically fatal, but....
++           restore_page_device() has to set LockSafetyParams false so it can
++           configure the restored device correctly - in normal operation, that
++           gets reset by that configuration. If we hit an error, though, that
++           may not happen -  at least ensure we keep the setting through the
++           error.
++         */
++        gs_currentdevice_inline(igs)->LockSafetyParams = saveLockSafety;
++    }
++    return code;
+ }
+ 
+ /* <gstate> setgstate - */
+diff --git a/psi/zvmem.c b/psi/zvmem.c
+index 44cd7a8..87a0a4f 100644
+--- a/psi/zvmem.c
++++ b/psi/zvmem.c
+@@ -99,19 +99,18 @@ zsave(i_ctx_t *i_ctx_p)
+ static int restore_check_operand(os_ptr, alloc_save_t **, gs_dual_memory_t *);
+ static int restore_check_stack(const i_ctx_t *i_ctx_p, const ref_stack_t *, const alloc_save_t *, bool);
+ static void restore_fix_stack(i_ctx_t *i_ctx_p, ref_stack_t *, const alloc_save_t *, bool);
++
++/* Do as many up front checks of the save object as we reasonably can */
+ 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_debug2m('u', imemory, "[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);
+@@ -120,14 +119,37 @@ zrestore(i_ctx_t *i_ctx_p)
+     {
+         int code;
+ 
+-        if ((code = restore_check_stack(i_ctx_p, &o_stack, asave, false)) < 0 ||
+-            (code = restore_check_stack(i_ctx_p, &e_stack, asave, true)) < 0 ||
+-            (code = restore_check_stack(i_ctx_p, &d_stack, asave, false)) < 0
++        if ((code = restore_check_stack(i_ctx_p, &o_stack, *asave, false)) < 0 ||
++            (code = restore_check_stack(i_ctx_p, &e_stack, *asave, true)) < 0 ||
++            (code = restore_check_stack(i_ctx_p, &d_stack, *asave, false)) < 0
+             ) {
+             osp++;
+             return code;
+         }
+     }
++    osp++;
++    return 0;
++}
++
++/* the semantics of restore differ slightly between Level 1 and
++   Level 2 and later - the latter includes 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(i_ctx_p, &o_stack, asave, false);
+@@ -170,9 +192,24 @@ 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. */
+ static int
+ restore_check_operand(os_ptr op, alloc_save_t ** pasave,
+@@ -193,6 +230,7 @@ restore_check_operand(os_ptr op, alloc_save_t ** pasave,
+     *pasave = asave;
+     return 0;
+ }
++
+ /* Check a stack to make sure all its elements are older than a save. */
+ static int
+ restore_check_stack(const i_ctx_t *i_ctx_p, const ref_stack_t * pstack,
diff --git a/ghostscript/ghostpdl.git-78911a01.patch b/ghostscript/ghostpdl.git-78911a01.patch
new file mode 100644
index 000000000..e1434fbea
--- /dev/null
+++ b/ghostscript/ghostpdl.git-78911a01.patch
@@ -0,0 +1,30 @@
+From: Chris Liddell <chris.liddell at artifex.com>
+Date: Thu, 23 Aug 2018 08:54:59 +0000 (+0100)
+Subject: Bug 699654: Check the restore operand type
+X-Git-Url: http://git.ghostscript.com/?p=ghostpdl.git;a=commitdiff_plain;h=78911a01
+
+Bug 699654: Check the restore operand type
+
+The primary function that implements restore correctly checked its parameter,
+but a function that does some preliminary work for the restore (gstate and
+device handling) did not check.
+
+So, even though the restore correctly errored out, it left things partially done
+and, in particular, the device in partially restored state. Meaning the
+LockSafetyParams was not correctly set.
+---
+
+diff --git a/psi/zdevice2.c b/psi/zdevice2.c
+index de16dd2..9fbb4e3 100644
+--- a/psi/zdevice2.c
++++ b/psi/zdevice2.c
+@@ -312,6 +312,9 @@ z2grestoreall(i_ctx_t *i_ctx_p)
+ static int
+ z2restore(i_ctx_t *i_ctx_p)
+ {
++    os_ptr op = osp;
++    check_type(*op, t_save);
++
+     while (gs_gstate_saved(gs_gstate_saved(igs))) {
+         if (restore_page_device(igs, gs_gstate_saved(igs)))
+             return push_callout(i_ctx_p, "%restore1pagedevice");
diff --git a/ghostscript/ghostpdl.git-8e9ce501.patch b/ghostscript/ghostpdl.git-8e9ce501.patch
new file mode 100644
index 000000000..a4790d8a2
--- /dev/null
+++ b/ghostscript/ghostpdl.git-8e9ce501.patch
@@ -0,0 +1,48 @@
+From: Ken Sharp <ken.sharp at artifex.com>
+Date: Thu, 23 Aug 2018 14:42:02 +0000 (+0100)
+Subject: Bug 699665 "memory corruption in aesdecode"
+X-Git-Url: http://git.ghostscript.com/?p=ghostpdl.git;a=commitdiff_plain;h=8e9ce501
+
+Bug 699665 "memory corruption in aesdecode"
+
+The specimen file calls aesdecode without specifying the key to be
+used, though it does manage to do enough work with the PDF interpreter
+routines to get access to aesdecode (which isn't normally available).
+
+This causes us to read uninitialised memory, which can (and often does)
+lead to a segmentation fault.
+
+In this commit we set the key to NULL explicitly during intialisation
+and then check it before we read it. If its NULL we just return.
+
+It seems bizarre that we don't return error codes, we should probably
+look into that at some point, but this prevents the code trying to
+read uninitialised memory.
+---
+
+diff --git a/base/aes.c b/base/aes.c
+index a6bce93..e86f000 100644
+--- a/base/aes.c
++++ b/base/aes.c
+@@ -662,6 +662,9 @@ void aes_crypt_ecb( aes_context *ctx,
+     }
+ #endif
+ 
++    if (ctx == NULL || ctx->rk == NULL)
++        return;
++
+     RK = ctx->rk;
+ 
+     GET_ULONG_LE( X0, input,  0 ); X0 ^= *RK++;
+diff --git a/base/saes.c b/base/saes.c
+index 6db0e8b..307ed74 100644
+--- a/base/saes.c
++++ b/base/saes.c
+@@ -120,6 +120,7 @@ s_aes_process(stream_state * ss, stream_cursor_read * pr,
+         gs_throw(gs_error_VMerror, "could not allocate aes context");
+         return ERRC;
+       }
++      memset(state->ctx, 0x00, sizeof(aes_context));
+       if (state->keylength < 1 || state->keylength > SAES_MAX_KEYLENGTH) {
+         gs_throw1(gs_error_rangecheck, "invalid aes key length (%d bytes)",
+                 state->keylength);
diff --git a/ghostscript/ghostpdl.git-a054156d.patch b/ghostscript/ghostpdl.git-a054156d.patch
new file mode 100644
index 000000000..50faf184e
--- /dev/null
+++ b/ghostscript/ghostpdl.git-a054156d.patch
@@ -0,0 +1,51 @@
+From: Chris Liddell <chris.liddell at artifex.com>
+Date: Tue, 21 Aug 2018 19:17:51 +0000 (+0100)
+Subject: Bug 699658: Fix handling of pre-SAFER opened files.
+X-Git-Url: http://git.ghostscript.com/?p=ghostpdl.git;a=commitdiff_plain;h=a054156d
+
+Bug 699658: Fix handling of pre-SAFER opened files.
+
+Temp files opened for writing before SAFER is engaged are not subject to the
+SAFER restrictions - that is handled by recording in a dictionary, and
+checking that as part of the permissions checks.
+
+By adding a custom error handler for invalidaccess, that allowed the filename
+to be added to the dictionary (despite the attempted open throwing the error)
+thus meaning subsequent accesses were erroneously permitted.
+---
+
+diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
+index a6e49f0..5a5a428 100644
+--- a/Resource/Init/gs_init.ps
++++ b/Resource/Init/gs_init.ps
+@@ -2036,6 +2036,19 @@ readonly def
+             concatstrings concatstrings .generate_dir_list_templates
+         } if
+       ]
++      /PermitFileWriting [
++          currentuserparams /PermitFileWriting get aload pop
++          (TMPDIR) getenv not
++          {
++            (TEMP) getenv not
++            {
++              (TMP) getenv not
++              {
++                (/temp) (/tmp)
++              } if
++            } if
++          } if
++      ]
+       /LockFilePermissions //true
+     >> setuserparams
+   }
+@@ -2122,7 +2135,9 @@ readonly def
+ % the file can be deleted later, even if SAFER is set.
+ /.tempfile {
+   .tempfile	% filename file
+-  //SAFETY /tempfiles get 2 .argindex //true .forceput
++    //SAFETY /safe get not { % only add the filename if we're not yet safe
++    //SAFETY /tempfiles get 2 .argindex //true .forceput
++  } if
+ } .bind executeonly odef
+ 
+ % If we are running in SAFER mode, lock things down
diff --git a/ghostscript/ghostpdl.git-b326a716.patch b/ghostscript/ghostpdl.git-b326a716.patch
new file mode 100644
index 000000000..c5c167cdb
--- /dev/null
+++ b/ghostscript/ghostpdl.git-b326a716.patch
@@ -0,0 +1,26 @@
+From: Chris Liddell <chris.liddell at artifex.com>
+Date: Tue, 21 Aug 2018 15:24:05 +0000 (+0100)
+Subject: Bug 699655: Properly check the return value....
+X-Git-Url: http://git.ghostscript.com/?p=ghostpdl.git;a=commitdiff_plain;h=b326a716
+
+Bug 699655: Properly check the return value....
+
+...when getting a value from a dictionary
+---
+
+diff --git a/psi/zcolor.c b/psi/zcolor.c
+index 4c0f258..e27baf9 100644
+--- a/psi/zcolor.c
++++ b/psi/zcolor.c
+@@ -283,8 +283,9 @@ zsetcolor(i_ctx_t * i_ctx_p)
+         if (r_has_type(op, t_dictionary)) {
+             ref     *pImpl, pPatInst;
+ 
+-            code = dict_find_string(op, "Implementation", &pImpl);
+-            if (code != 0) {
++            if ((code = dict_find_string(op, "Implementation", &pImpl)) < 0)
++                return code;
++            if (code > 0) {
+                 code = array_get(imemory, pImpl, 0, &pPatInst);
+                 if (code < 0)
+                     return code;
diff --git a/ghostscript/ghostpdl.git-b575e1ec.patch b/ghostscript/ghostpdl.git-b575e1ec.patch
new file mode 100644
index 000000000..d5d15a26b
--- /dev/null
+++ b/ghostscript/ghostpdl.git-b575e1ec.patch
@@ -0,0 +1,33 @@
+From: Chris Liddell <chris.liddell at artifex.com>
+Date: Thu, 23 Aug 2018 11:20:56 +0000 (+0100)
+Subject: Bug 699668: handle stack overflow during error handling
+X-Git-Url: http://git.ghostscript.com/?p=ghostpdl.git;a=commitdiff_plain;h=b575e1ec
+
+Bug 699668: handle stack overflow during error handling
+
+When handling a Postscript error, we push the object throwing the error onto
+the operand stack for the error handling procedure to access - we were not
+checking the available stack before doing so, thus causing a crash.
+
+Basically, if we get a stack overflow when already handling an error, we're out
+of options, return to the caller with a fatal error.
+---
+
+diff --git a/psi/interp.c b/psi/interp.c
+index 8b49556..6150838 100644
+--- a/psi/interp.c
++++ b/psi/interp.c
+@@ -676,7 +676,12 @@ again:
+     /* Push the error object on the operand stack if appropriate. */
+     if (!GS_ERROR_IS_INTERRUPT(code)) {
+         /* Replace the error object if within an oparray or .errorexec. */
+-        *++osp = *perror_object;
++        osp++;
++        if (osp >= ostop) {
++            *pexit_code = gs_error_Fatal;
++            return_error(gs_error_Fatal);
++        }
++        *osp = *perror_object;
+         errorexec_find(i_ctx_p, osp);
+     }
+     goto again;
diff --git a/ghostscript/ghostpdl.git-c3476dde.patch b/ghostscript/ghostpdl.git-c3476dde.patch
new file mode 100644
index 000000000..cf2a2ebbf
--- /dev/null
+++ b/ghostscript/ghostpdl.git-c3476dde.patch
@@ -0,0 +1,43 @@
+From: Chris Liddell <chris.liddell at artifex.com>
+Date: Tue, 21 Aug 2018 15:42:45 +0000 (+0100)
+Subject: Bug 699656: Handle LockDistillerParams not being a boolean
+X-Git-Url: http://git.ghostscript.com/?p=ghostpdl.git;a=commitdiff_plain;h=c3476dde
+
+Bug 699656: Handle LockDistillerParams not being a boolean
+
+This caused a function call commented as "Can't fail" to fail, and resulted
+in memory correuption and a segfault.
+---
+
+diff --git a/devices/vector/gdevpdfp.c b/devices/vector/gdevpdfp.c
+index e942682..7c58af7 100644
+--- a/devices/vector/gdevpdfp.c
++++ b/devices/vector/gdevpdfp.c
+@@ -364,7 +364,7 @@ gdev_pdf_put_params_impl(gx_device * dev, const gx_device_pdf * save_dev, gs_par
+      * LockDistillerParams is read again, and reset if necessary, in
+      * psdf_put_params.
+      */
+-    ecode = param_read_bool(plist, "LockDistillerParams", &locked);
++    ecode = param_read_bool(plist, (param_name = "LockDistillerParams"), &locked);
+     if (ecode < 0)
+         param_signal_error(plist, param_name, ecode);
+ 
+diff --git a/psi/iparam.c b/psi/iparam.c
+index 68c20d4..0279455 100644
+--- a/psi/iparam.c
++++ b/psi/iparam.c
+@@ -822,10 +822,11 @@ static int
+ ref_param_read_signal_error(gs_param_list * plist, gs_param_name pkey, int code)
+ {
+     iparam_list *const iplist = (iparam_list *) plist;
+-    iparam_loc loc;
++    iparam_loc loc = {0};
+ 
+-    ref_param_read(iplist, pkey, &loc, -1);	/* can't fail */
+-    *loc.presult = code;
++    ref_param_read(iplist, pkey, &loc, -1);
++    if (loc.presult)
++        *loc.presult = code;
+     switch (ref_param_read_get_policy(plist, pkey)) {
+         case gs_param_policy_ignore:
+             return 0;
diff --git a/ghostscript/ghostpdl.git-c432131c.patch b/ghostscript/ghostpdl.git-c432131c.patch
new file mode 100644
index 000000000..849b852e0
--- /dev/null
+++ b/ghostscript/ghostpdl.git-c432131c.patch
@@ -0,0 +1,109 @@
+From: Chris Liddell <chris.liddell at artifex.com>
+Date: Thu, 23 Aug 2018 13:13:25 +0000 (+0100)
+Subject: Bug 699661: Avoid sharing pointers between pdf14 compositors
+X-Git-Url: http://git.ghostscript.com/?p=ghostpdl.git;a=commitdiff_plain;h=c432131c
+
+Bug 699661: Avoid sharing pointers between pdf14 compositors
+
+If a copdevice is triggered when the pdf14 compositor is the device, we make
+a copy of the device, then throw an error because, by default we're only allowed
+to copy the device prototype - then freeing it calls the finalize, which frees
+several pointers shared with the parent.
+
+Make a pdf14 specific finish_copydevice() which NULLs the relevant pointers,
+before, possibly, throwing the same error as the default method.
+
+This also highlighted a problem with reopening the X11 devices, where a custom
+error handler could be replaced with itself, meaning it also called itself,
+and infifite recursion resulted.
+
+Keep a note of if the handler replacement has been done, and don't do it a
+second time.
+---
+
+diff --git a/base/gdevp14.c b/base/gdevp14.c
+index d9f8e79..eb9cc23 100644
+--- a/base/gdevp14.c
++++ b/base/gdevp14.c
+@@ -178,6 +178,7 @@ static	dev_proc_fill_mask(pdf14_fill_mask);
+ static	dev_proc_stroke_path(pdf14_stroke_path);
+ static	dev_proc_begin_typed_image(pdf14_begin_typed_image);
+ static	dev_proc_text_begin(pdf14_text_begin);
++static  dev_proc_finish_copydevice(pdf14_finish_copydevice);
+ static	dev_proc_create_compositor(pdf14_create_compositor);
+ static	dev_proc_create_compositor(pdf14_forward_create_compositor);
+ static	dev_proc_begin_transparency_group(pdf14_begin_transparency_group);
+@@ -245,7 +246,7 @@ static	const gx_color_map_procs *
+         pdf14_create_compositor,	/* create_compositor */\
+         NULL,				/* get_hardware_params */\
+         pdf14_text_begin,		/* text_begin */\
+-        NULL,				/* finish_copydevice */\
++        pdf14_finish_copydevice,        /* finish_copydevice */\
+         pdf14_begin_transparency_group,\
+         pdf14_end_transparency_group,\
+         pdf14_begin_transparency_mask,\
+@@ -3935,6 +3936,19 @@ pdf14_text_begin(gx_device * dev, gs_gstate * pgs,
+     return code;
+ }
+ 
++static	int
++pdf14_finish_copydevice(gx_device *new_dev, const gx_device *from_dev)
++{
++    pdf14_device *pdev = (pdf14_device*)new_dev;
++
++    pdev->ctx = NULL;
++    pdev->trans_group_parent_cmap_procs = NULL;
++    pdev->smaskcolor = NULL;
++
++    /* Only allow copying the prototype. */
++    return (from_dev->memory ? gs_note_error(gs_error_rangecheck) : 0);
++}
++
+ /*
+  * Implement copy_mono by filling lots of small rectangles.
+  */
+@@ -8093,6 +8107,7 @@ c_pdf14trans_clist_read_update(gs_composite_t *	pcte, gx_device	* cdev,
+                        before reopening the device */
+                     if (p14dev->ctx != NULL) {
+                         pdf14_ctx_free(p14dev->ctx);
++                        p14dev->ctx = NULL;
+                     }
+                     dev_proc(tdev, open_device) (tdev);
+                 }
+diff --git a/devices/gdevxini.c b/devices/gdevxini.c
+index 8511eac..23b8c35 100644
+--- a/devices/gdevxini.c
++++ b/devices/gdevxini.c
+@@ -59,7 +59,8 @@ static struct xv_ {
+     Boolean alloc_error;
+     XErrorHandler orighandler;
+     XErrorHandler oldhandler;
+-} x_error_handler;
++    Boolean set;
++} x_error_handler = {0};
+ 
+ static int
+ x_catch_alloc(Display * dpy, XErrorEvent * err)
+@@ -74,7 +75,8 @@ x_catch_alloc(Display * dpy, XErrorEvent * err)
+ int
+ x_catch_free_colors(Display * dpy, XErrorEvent * err)
+ {
+-    if (err->request_code == X_FreeColors)
++    if (err->request_code == X_FreeColors ||
++        x_error_handler.orighandler == x_catch_free_colors)
+         return 0;
+     return x_error_handler.orighandler(dpy, err);
+ }
+@@ -274,8 +276,10 @@ gdev_x_open(gx_device_X * xdev)
+         return_error(gs_error_ioerror);
+     }
+     /* Buggy X servers may cause a Bad Access on XFreeColors. */
+-    x_error_handler.orighandler = XSetErrorHandler(x_catch_free_colors);
+-
++    if (!x_error_handler.set) {
++        x_error_handler.orighandler = XSetErrorHandler(x_catch_free_colors);
++        x_error_handler.set = True;
++    }
+     /* Get X Resources.  Use the toolkit for this. */
+     XtToolkitInitialize();
+     app_con = XtCreateApplicationContext();
diff --git a/ghostscript/ghostpdl.git-e01e77a3.patch b/ghostscript/ghostpdl.git-e01e77a3.patch
new file mode 100644
index 000000000..5859c4960
--- /dev/null
+++ b/ghostscript/ghostpdl.git-e01e77a3.patch
@@ -0,0 +1,27 @@
+From: Ken Sharp <ken.sharp at artifex.com>
+Date: Fri, 24 Aug 2018 11:44:26 +0000 (+0100)
+Subject: Hide the .shfill operator
+X-Git-Url: http://git.ghostscript.com/?p=ghostpdl.git;a=commitdiff_plain;h=e01e77a3
+
+Hide the .shfill operator
+
+Commit 0b6cd1918e1ec4ffd087400a754a845180a4522b was supposed to make
+the .shfill operator unobtainable, but I accidentally left a comment
+in the line doing so.
+
+Fix it here, without this the operator can still be exploited.
+---
+
+diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
+index bc17d42..db3f7fe 100644
+--- a/Resource/Init/gs_init.ps
++++ b/Resource/Init/gs_init.ps
+@@ -2197,7 +2197,7 @@ SAFER { .setsafeglobal } if
+ /.oserrno /.setoserrno /.oserrorstring /.getCPSImode
+ /.getscanconverter /.setscanconverter /.type1encrypt /.type1decrypt/.languagelevel /.setlanguagelevel /.eqproc /.fillpage /.buildpattern1 /.saslprep
+ /.buildshading1 /.buildshading2 /.buildshading3 /.buildshading4 /.buildshading5 /.buildshading6 /.buildshading7 /.buildshadingpattern
+-%/.shfill /.argindex /.bytestring /.namestring /.stringbreak /.stringmatch /.globalvmarray /.globalvmdict /.globalvmpackedarray /.globalvmstring
++/.shfill /.argindex /.bytestring /.namestring /.stringbreak /.stringmatch /.globalvmarray /.globalvmdict /.globalvmpackedarray /.globalvmstring
+ /.localvmarray /.localvmdict /.localvmpackedarray /.localvmstring /.systemvmarray /.systemvmdict /.systemvmpackedarray /.systemvmstring /.systemvmfile /.systemvmlibfile
+ /.systemvmSFD /.settrapparams /.currentsystemparams /.currentuserparams /.getsystemparam /.getuserparam /.setsystemparams /.setuserparams
+ /.checkpassword /.locale_to_utf8 /.currentglobal /.gcheck /.imagepath


More information about the CRUX mailing list