A PostScript interpreter and renderer
CentOS Sources
2018-12-03 2796d4231d6c7bc5d71b5361828c16f2edaea173
commit | author | age
8812f8 1 From: Chris Liddell <chris.liddell@artifex.com>
CS 2 Date: Tue, 21 Aug 2018 19:17:05 +0000 (+0100)
3 Subject: Bug 699657: properly apply file permissions to .tempfile
4
5 Bug 699657: properly apply file permissions to .tempfile
6
7 https://git.ghostscript.com/?p=ghostpdl.git;a=commit;h=0d3901189f245232f0161addf215d7268c4d05a3
8 ---
9
10 diff -up a/psi/zfile.c.cve-2018-15908 b/psi/zfile.c
11 --- a/psi/zfile.c.cve-2018-15908    2018-11-14 15:13:31.249625819 +0100
12 +++ b/psi/zfile.c    2018-11-14 15:14:16.933831779 +0100
13 @@ -121,7 +121,7 @@ make_invalid_file(i_ctx_t *i_ctx_p, ref
14  /* strings of the permitgroup array. */
15  static int
16  check_file_permissions_reduced(i_ctx_t *i_ctx_p, const char *fname, int len,
17 -                        const char *permitgroup)
18 +                        gx_io_device *iodev, const char *permitgroup)
19  {
20      long i;
21      ref *permitlist = NULL;
22 @@ -131,8 +131,14 @@ check_file_permissions_reduced(i_ctx_t *
23      bool use_windows_pathsep = (gs_file_name_check_separator(win_sep2, 1, win_sep2) == 1);
24      uint plen = gp_file_name_parents(fname, len);
25  
26 -    /* Assuming a reduced file name. */
27 +    /* we're protecting arbitrary file system accesses, not Postscript device accesses.
28 +     * Although, note that %pipe% is explicitly checked for and disallowed elsewhere
29 +     */
30 +    if (iodev && iodev != iodev_default(imemory)) {
31 +        return 0;
32 +    }
33  
34 +    /* Assuming a reduced file name. */
35      if (dict_find_string(&(i_ctx_p->userparams), permitgroup, &permitlist) <= 0)
36          return 0;       /* if Permissions not found, just allow access */
37  
38 @@ -187,14 +193,14 @@ check_file_permissions_reduced(i_ctx_t *
39  /* strings of the permitgroup array */
40  static int
41  check_file_permissions(i_ctx_t *i_ctx_p, const char *fname, int len,
42 -                        const char *permitgroup)
43 +                        gx_io_device *iodev, const char *permitgroup)
44  {
45      char fname_reduced[gp_file_name_sizeof];
46      uint rlen = sizeof(fname_reduced);
47  
48      if (gp_file_name_reduce(fname, len, fname_reduced, &rlen) != gp_combine_success)
49          return e_invalidaccess;         /* fail if we couldn't reduce */
50 -    return check_file_permissions_reduced(i_ctx_p, fname_reduced, rlen, permitgroup);
51 +    return check_file_permissions_reduced(i_ctx_p, fname_reduced, rlen, iodev, permitgroup);
52  }
53  
54  /* <name_string> <access_string> file <file> */
55 @@ -298,7 +304,7 @@ zdeletefile(i_ctx_t *i_ctx_p)
56          return code;
57      if (pname.iodev == iodev_default(imemory)) {
58          if ((code = check_file_permissions(i_ctx_p, pname.fname, pname.len,
59 -                "PermitFileControl")) < 0 &&
60 +                pname.iodev, "PermitFileControl")) < 0 &&
61                   !file_is_tempfile(i_ctx_p, op->value.bytes, r_size(op))) {
62              return code;
63          }
64 @@ -382,7 +388,7 @@ file_continue(i_ctx_t *i_ctx_p)
65          } else if (code > len)      /* overran string */
66              return_error(gs_error_rangecheck);
67          else if (iodev != iodev_default(imemory)
68 -              || (check_file_permissions_reduced(i_ctx_p, (char *)pscratch->value.bytes, code + devlen, "PermitFileReading")) == 0) {
69 +              || (check_file_permissions_reduced(i_ctx_p, (char *)pscratch->value.bytes, code + devlen, NULL, "PermitFileReading")) == 0) {
70              push(1);
71              ref_assign(op, pscratch);
72              r_set_size(op, code + devlen);
73 @@ -432,12 +438,12 @@ zrenamefile(i_ctx_t *i_ctx_p)
74                   * and FileWriting permissions to the destination file/path.
75                   */
76                ((check_file_permissions(i_ctx_p, pname1.fname, pname1.len,
77 -                                        "PermitFileControl") < 0 &&
78 +                                        pname1.iodev, "PermitFileControl") < 0 &&
79                    !file_is_tempfile(i_ctx_p, op[-1].value.bytes, r_size(op - 1))) ||
80                (check_file_permissions(i_ctx_p, pname2.fname, pname2.len,
81 -                                        "PermitFileControl") < 0 ||
82 +                                        pname2.iodev, "PermitFileControl") < 0 ||
83                check_file_permissions(i_ctx_p, pname2.fname, pname2.len,
84 -                                        "PermitFileWriting") < 0 )))) {
85 +                                        pname2.iodev, "PermitFileWriting") < 0 )))) {
86              code = gs_note_error(e_invalidfileaccess);
87          } else {
88              code = (*pname1.iodev->procs.rename_file)(pname1.iodev,
89 @@ -484,8 +490,11 @@ zstatus(i_ctx_t *i_ctx_p)
90                  code = gs_terminate_file_name(&pname, imemory, "status");
91                  if (code < 0)
92                      return code;
93 -                code = (*pname.iodev->procs.file_status)(pname.iodev,
94 +                if ((code = check_file_permissions(i_ctx_p, pname.fname, pname.len,
95 +                                       pname.iodev, "PermitFileReading")) >= 0) {
96 +                    code = (*pname.iodev->procs.file_status)(pname.iodev,
97                                                         pname.fname, &fstat);
98 +                }
99                  switch (code) {
100                      case 0:
101                          check_ostack(4);
102 @@ -694,8 +703,24 @@ ztempfile(i_ctx_t *i_ctx_p)
103      }
104  
105      if (gp_file_name_is_absolute(pstr, strlen(pstr))) {
106 -        if (check_file_permissions(i_ctx_p, pstr, strlen(pstr),
107 -                                   "PermitFileWriting") < 0) {
108 +        int plen = strlen(pstr);
109 +        const char *sep = gp_file_name_separator();
110 +#ifdef DEBUG
111 +        int seplen = strlen(sep);
112 +        if (seplen != 1)
113 +            return_error(gs_error_Fatal);
114 +#endif
115 +        /* strip off the file name prefix, leave just the directory name
116 +         * so we can check if we are allowed to write to it
117 +         */
118 +        for ( ; plen >=0; plen--) {
119 +            if (pstr[plen] == sep[0])
120 +                break;
121 +        }
122 +        memcpy(fname, pstr, plen);
123 +        fname[plen] = '\0';
124 +        if (check_file_permissions(i_ctx_p, fname, strlen(fname),
125 +                                   NULL, "PermitFileWriting") < 0) {
126              return_error(e_invalidfileaccess);
127          }
128      } else if (!prefix_is_simple(pstr)) {
129 @@ -837,6 +862,7 @@ zopen_file(i_ctx_t *i_ctx_p, const gs_pa
130             const char *file_access, stream **ps, gs_memory_t *mem)
131  {
132      gx_io_device *const iodev = pfn->iodev;
133 +    int code = 0;
134  
135      if (pfn->fname == NULL)     /* just a device */
136          return iodev->procs.open_device(iodev, file_access, ps, mem);
137 @@ -847,7 +873,7 @@ zopen_file(i_ctx_t *i_ctx_p, const gs_pa
138              open_file = iodev_os_open_file;
139          /* Check OS files to make sure we allow the type of access */
140          if (open_file == iodev_os_open_file) {
141 -            int code = check_file_permissions(i_ctx_p, pfn->fname, pfn->len,
142 +            code = check_file_permissions(i_ctx_p, pfn->fname, pfn->len, pfn->iodev,
143                  file_access[0] == 'r' ? "PermitFileReading" : "PermitFileWriting");
144  
145              if (code < 0 && !file_is_tempfile(i_ctx_p,
146 @@ -894,7 +920,7 @@ check_file_permissions_aux(i_ctx_t *i_ct
147      /* fname must be reduced. */
148      if (i_ctx_p == NULL)
149          return 0;
150 -    if (check_file_permissions_reduced(i_ctx_p, fname, flen, "PermitFileReading") < 0)
151 +    if (check_file_permissions_reduced(i_ctx_p, fname, flen, NULL, "PermitFileReading") < 0)
152          return_error(e_invalidfileaccess);
153      return 0;
154  }
2796d4 155