Blame SOURCES/ghostscript-cve-2018-15908.patch

8812f8
From: Chris Liddell <chris.liddell@artifex.com>
8812f8
Date: Tue, 21 Aug 2018 19:17:05 +0000 (+0100)
8812f8
Subject: Bug 699657: properly apply file permissions to .tempfile
8812f8
8812f8
Bug 699657: properly apply file permissions to .tempfile
8812f8
8812f8
https://git.ghostscript.com/?p=ghostpdl.git;a=commit;h=0d3901189f245232f0161addf215d7268c4d05a3
8812f8
---
8812f8
8812f8
diff -up a/psi/zfile.c.cve-2018-15908 b/psi/zfile.c
8812f8
--- a/psi/zfile.c.cve-2018-15908	2018-11-14 15:13:31.249625819 +0100
8812f8
+++ b/psi/zfile.c	2018-11-14 15:14:16.933831779 +0100
8812f8
@@ -121,7 +121,7 @@ make_invalid_file(i_ctx_t *i_ctx_p, ref
8812f8
 /* strings of the permitgroup array. */
8812f8
 static int
8812f8
 check_file_permissions_reduced(i_ctx_t *i_ctx_p, const char *fname, int len,
8812f8
-                        const char *permitgroup)
8812f8
+                        gx_io_device *iodev, const char *permitgroup)
8812f8
 {
8812f8
     long i;
8812f8
     ref *permitlist = NULL;
8812f8
@@ -131,8 +131,14 @@ check_file_permissions_reduced(i_ctx_t *
8812f8
     bool use_windows_pathsep = (gs_file_name_check_separator(win_sep2, 1, win_sep2) == 1);
8812f8
     uint plen = gp_file_name_parents(fname, len);
8812f8
 
8812f8
-    /* Assuming a reduced file name. */
8812f8
+    /* we're protecting arbitrary file system accesses, not Postscript device accesses.
8812f8
+     * Although, note that %pipe% is explicitly checked for and disallowed elsewhere
8812f8
+     */
8812f8
+    if (iodev && iodev != iodev_default(imemory)) {
8812f8
+        return 0;
8812f8
+    }
8812f8
 
8812f8
+    /* Assuming a reduced file name. */
8812f8
     if (dict_find_string(&(i_ctx_p->userparams), permitgroup, &permitlist) <= 0)
8812f8
         return 0;       /* if Permissions not found, just allow access */
8812f8
 
8812f8
@@ -187,14 +193,14 @@ check_file_permissions_reduced(i_ctx_t *
8812f8
 /* strings of the permitgroup array */
8812f8
 static int
8812f8
 check_file_permissions(i_ctx_t *i_ctx_p, const char *fname, int len,
8812f8
-                        const char *permitgroup)
8812f8
+                        gx_io_device *iodev, const char *permitgroup)
8812f8
 {
8812f8
     char fname_reduced[gp_file_name_sizeof];
8812f8
     uint rlen = sizeof(fname_reduced);
8812f8
 
8812f8
     if (gp_file_name_reduce(fname, len, fname_reduced, &rlen) != gp_combine_success)
8812f8
         return e_invalidaccess;         /* fail if we couldn't reduce */
8812f8
-    return check_file_permissions_reduced(i_ctx_p, fname_reduced, rlen, permitgroup);
8812f8
+    return check_file_permissions_reduced(i_ctx_p, fname_reduced, rlen, iodev, permitgroup);
8812f8
 }
8812f8
 
8812f8
 /* <name_string> <access_string> file <file> */
8812f8
@@ -298,7 +304,7 @@ zdeletefile(i_ctx_t *i_ctx_p)
8812f8
         return code;
8812f8
     if (pname.iodev == iodev_default(imemory)) {
8812f8
         if ((code = check_file_permissions(i_ctx_p, pname.fname, pname.len,
8812f8
-                "PermitFileControl")) < 0 &&
8812f8
+                pname.iodev, "PermitFileControl")) < 0 &&
8812f8
                  !file_is_tempfile(i_ctx_p, op->value.bytes, r_size(op))) {
8812f8
             return code;
8812f8
         }
8812f8
@@ -382,7 +388,7 @@ file_continue(i_ctx_t *i_ctx_p)
8812f8
         } else if (code > len)      /* overran string */
8812f8
             return_error(gs_error_rangecheck);
8812f8
         else if (iodev != iodev_default(imemory)
8812f8
-              || (check_file_permissions_reduced(i_ctx_p, (char *)pscratch->value.bytes, code + devlen, "PermitFileReading")) == 0) {
8812f8
+              || (check_file_permissions_reduced(i_ctx_p, (char *)pscratch->value.bytes, code + devlen, NULL, "PermitFileReading")) == 0) {
8812f8
             push(1);
8812f8
             ref_assign(op, pscratch);
8812f8
             r_set_size(op, code + devlen);
8812f8
@@ -432,12 +438,12 @@ zrenamefile(i_ctx_t *i_ctx_p)
8812f8
                  * and FileWriting permissions to the destination file/path.
8812f8
                  */
8812f8
               ((check_file_permissions(i_ctx_p, pname1.fname, pname1.len,
8812f8
-                                        "PermitFileControl") < 0 &&
8812f8
+                                        pname1.iodev, "PermitFileControl") < 0 &&
8812f8
                   !file_is_tempfile(i_ctx_p, op[-1].value.bytes, r_size(op - 1))) ||
8812f8
               (check_file_permissions(i_ctx_p, pname2.fname, pname2.len,
8812f8
-                                        "PermitFileControl") < 0 ||
8812f8
+                                        pname2.iodev, "PermitFileControl") < 0 ||
8812f8
               check_file_permissions(i_ctx_p, pname2.fname, pname2.len,
8812f8
-                                        "PermitFileWriting") < 0 )))) {
8812f8
+                                        pname2.iodev, "PermitFileWriting") < 0 )))) {
8812f8
             code = gs_note_error(e_invalidfileaccess);
8812f8
         } else {
8812f8
             code = (*pname1.iodev->procs.rename_file)(pname1.iodev,
8812f8
@@ -484,8 +490,11 @@ zstatus(i_ctx_t *i_ctx_p)
8812f8
                 code = gs_terminate_file_name(&pname, imemory, "status");
8812f8
                 if (code < 0)
8812f8
                     return code;
8812f8
-                code = (*pname.iodev->procs.file_status)(pname.iodev,
8812f8
+                if ((code = check_file_permissions(i_ctx_p, pname.fname, pname.len,
8812f8
+                                       pname.iodev, "PermitFileReading")) >= 0) {
8812f8
+                    code = (*pname.iodev->procs.file_status)(pname.iodev,
8812f8
                                                        pname.fname, &fstat);
8812f8
+                }
8812f8
                 switch (code) {
8812f8
                     case 0:
8812f8
                         check_ostack(4);
8812f8
@@ -694,8 +703,24 @@ ztempfile(i_ctx_t *i_ctx_p)
8812f8
     }
8812f8
 
8812f8
     if (gp_file_name_is_absolute(pstr, strlen(pstr))) {
8812f8
-        if (check_file_permissions(i_ctx_p, pstr, strlen(pstr),
8812f8
-                                   "PermitFileWriting") < 0) {
8812f8
+        int plen = strlen(pstr);
8812f8
+        const char *sep = gp_file_name_separator();
8812f8
+#ifdef DEBUG
8812f8
+        int seplen = strlen(sep);
8812f8
+        if (seplen != 1)
8812f8
+            return_error(gs_error_Fatal);
8812f8
+#endif
8812f8
+        /* strip off the file name prefix, leave just the directory name
8812f8
+         * so we can check if we are allowed to write to it
8812f8
+         */
8812f8
+        for ( ; plen >=0; plen--) {
8812f8
+            if (pstr[plen] == sep[0])
8812f8
+                break;
8812f8
+        }
8812f8
+        memcpy(fname, pstr, plen);
8812f8
+        fname[plen] = '\0';
8812f8
+        if (check_file_permissions(i_ctx_p, fname, strlen(fname),
8812f8
+                                   NULL, "PermitFileWriting") < 0) {
8812f8
             return_error(e_invalidfileaccess);
8812f8
         }
8812f8
     } else if (!prefix_is_simple(pstr)) {
8812f8
@@ -837,6 +862,7 @@ zopen_file(i_ctx_t *i_ctx_p, const gs_pa
8812f8
            const char *file_access, stream **ps, gs_memory_t *mem)
8812f8
 {
8812f8
     gx_io_device *const iodev = pfn->iodev;
8812f8
+    int code = 0;
8812f8
 
8812f8
     if (pfn->fname == NULL)     /* just a device */
8812f8
         return iodev->procs.open_device(iodev, file_access, ps, mem);
8812f8
@@ -847,7 +873,7 @@ zopen_file(i_ctx_t *i_ctx_p, const gs_pa
8812f8
             open_file = iodev_os_open_file;
8812f8
         /* Check OS files to make sure we allow the type of access */
8812f8
         if (open_file == iodev_os_open_file) {
8812f8
-            int code = check_file_permissions(i_ctx_p, pfn->fname, pfn->len,
8812f8
+            code = check_file_permissions(i_ctx_p, pfn->fname, pfn->len, pfn->iodev,
8812f8
                 file_access[0] == 'r' ? "PermitFileReading" : "PermitFileWriting");
8812f8
 
8812f8
             if (code < 0 && !file_is_tempfile(i_ctx_p,
8812f8
@@ -894,7 +920,7 @@ check_file_permissions_aux(i_ctx_t *i_ct
8812f8
     /* fname must be reduced. */
8812f8
     if (i_ctx_p == NULL)
8812f8
         return 0;
8812f8
-    if (check_file_permissions_reduced(i_ctx_p, fname, flen, "PermitFileReading") < 0)
8812f8
+    if (check_file_permissions_reduced(i_ctx_p, fname, flen, NULL, "PermitFileReading") < 0)
8812f8
         return_error(e_invalidfileaccess);
8812f8
     return 0;
8812f8
 }
2796d4