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