Brad Bishop | 1a4b7ee | 2018-12-16 17:11:34 -0800 | [diff] [blame^] | 1 | From 1f9a91c86bd56acf57826b9b0e020ebe1953e2ae Mon Sep 17 00:00:00 2001 |
| 2 | From: Chris Liddell <chris.liddell@artifex.com> |
| 3 | Date: Thu, 4 Oct 2018 10:42:13 +0100 |
| 4 | Subject: [PATCH 3/5] Bug 699832: add control over hiding error handlers. |
| 5 | |
| 6 | With a previous commit changing error handling in SAFER so the handler gets |
| 7 | passed a name object (rather than executable object), it is less critical to |
| 8 | hide the error handlers. |
| 9 | |
| 10 | This introduces a -dSAFERERRORS option to force only use of the default error |
| 11 | handlers. |
| 12 | |
| 13 | It also adds a .setsafererrors Postscript call, meaning a caller, without |
| 14 | -dSAFERERRORS, can create their own default error handlers (in errordict, as |
| 15 | normal), and then call .setsafererrors meaning their own handlers are always |
| 16 | called. |
| 17 | |
| 18 | With -dSAFERERRORS or after a call to .setsafererrors, .setsafererrors is |
| 19 | removed. |
| 20 | |
| 21 | CVE: CVE-2018-17961 |
| 22 | Upstream-Status: Backport [git://git.ghostscript.com/ghostpdl.git] |
| 23 | Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com> |
| 24 | --- |
| 25 | Resource/Init/gs_init.ps | 42 +++++++++++++++++++++++++++++------------ |
| 26 | psi/interp.c | 49 ++++++++++++++++++++++++++++-------------------- |
| 27 | 2 files changed, 59 insertions(+), 32 deletions(-) |
| 28 | |
| 29 | diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps |
| 30 | index bec307d..f952f32 100644 |
| 31 | --- a/Resource/Init/gs_init.ps |
| 32 | +++ b/Resource/Init/gs_init.ps |
| 33 | @@ -188,6 +188,16 @@ currentdict /DELAYSAFER known { /DELAYSAFER //true def /NOSAFER //true def } if |
| 34 | currentdict /PARANOIDSAFER known or % PARANOIDSAFER is equivalent |
| 35 | } |
| 36 | ifelse def |
| 37 | + |
| 38 | +/SAFERERRORS |
| 39 | +currentdict /NOSAFERERRORS known |
| 40 | +{ |
| 41 | + //false |
| 42 | +} |
| 43 | +{ |
| 44 | + currentdict /SAFERERRORS known |
| 45 | +} ifelse def |
| 46 | + |
| 47 | currentdict /SHORTERRORS known /SHORTERRORS exch def |
| 48 | currentdict /TTYPAUSE known /TTYPAUSE exch def |
| 49 | currentdict /WRITESYSTEMDICT known /WRITESYSTEMDICT exch def |
| 50 | @@ -1123,12 +1133,23 @@ errordict begin |
| 51 | } bind def |
| 52 | end % errordict |
| 53 | |
| 54 | -% Put all the default handlers in gserrordict |
| 55 | -gserrordict |
| 56 | -errordict {2 index 3 1 roll put} forall |
| 57 | -noaccess pop |
| 58 | -% remove the non-standard errors from errordict |
| 59 | +gserrordict /unknownerror errordict /unknownerror get put |
| 60 | errordict /unknownerror .undef |
| 61 | + |
| 62 | +/.SAFERERRORLIST ErrorNames def |
| 63 | +/.setsafererrors |
| 64 | +{ |
| 65 | +% Put all the requested handlers in gserrordict |
| 66 | + gserrordict |
| 67 | + //.SAFERERRORLIST |
| 68 | + {dup errordict exch get 2 index 3 1 roll put} forall |
| 69 | + noaccess pop |
| 70 | + systemdict /.setsafeerrors .forceundef |
| 71 | + systemdict /.SAFERERRORLIST .forceundef |
| 72 | +} bind executeonly odef |
| 73 | + |
| 74 | +SAFERERRORS {.setsafererrors} if |
| 75 | + |
| 76 | % Define a stable private copy of handleerror that we will always use under |
| 77 | % JOBSERVER mode. |
| 78 | /.GShandleerror errordict /handleerror get def |
| 79 | @@ -1760,18 +1781,15 @@ currentdict /.runlibfile .undef |
| 80 | |
| 81 | % Bind all the operators defined as procedures. |
| 82 | /.bindoperators % binds operators in currentdict |
| 83 | - { % Temporarily disable the typecheck error. |
| 84 | - errordict /typecheck 2 copy get |
| 85 | - errordict /typecheck { pop } put % pop the command |
| 86 | + { |
| 87 | currentdict |
| 88 | { dup type /operatortype eq |
| 89 | - { % This might be a real operator, so bind might cause a typecheck, |
| 90 | - % but we've made the error a no-op temporarily. |
| 91 | - .bind |
| 92 | + { |
| 93 | + % This might be a real operator, so bind might cause a typecheck |
| 94 | + {.bind} .internalstopped pop |
| 95 | } |
| 96 | if pop pop |
| 97 | } forall |
| 98 | - put |
| 99 | } def |
| 100 | DELAYBIND not { .bindoperators } if |
| 101 | |
| 102 | diff --git a/psi/interp.c b/psi/interp.c |
| 103 | index 3dd5f7a..cd894f9 100644 |
| 104 | --- a/psi/interp.c |
| 105 | +++ b/psi/interp.c |
| 106 | @@ -662,27 +662,18 @@ again: |
| 107 | if (gs_errorname(i_ctx_p, code, &error_name) < 0) |
| 108 | return code; /* out-of-range error code! */ |
| 109 | |
| 110 | - /* If LockFilePermissions is true, we only refer to gserrordict, which |
| 111 | - * is not accessible to Postcript jobs |
| 112 | + /* We refer to gserrordict first, which is not accessible to Postcript jobs |
| 113 | + * If we're running with SAFERERRORS all the handlers are copied to gserrordict |
| 114 | + * so we'll always find the default one. If not SAFERERRORS, only gs specific |
| 115 | + * errors are in gserrordict. |
| 116 | */ |
| 117 | - if (i_ctx_p->LockFilePermissions) { |
| 118 | - if (((dict_find_string(systemdict, "gserrordict", &perrordict) <= 0 || |
| 119 | - dict_find(perrordict, &error_name, &epref) <= 0)) |
| 120 | - ) |
| 121 | - return code; /* error name not in errordict??? */ |
| 122 | - } |
| 123 | - else { |
| 124 | - /* |
| 125 | - * For greater Adobe compatibility, only the standard PostScript errors |
| 126 | - * are defined in errordict; the rest are in gserrordict. |
| 127 | - */ |
| 128 | - if (dict_find_string(systemdict, "errordict", &perrordict) <= 0 || |
| 129 | - (dict_find(perrordict, &error_name, &epref) <= 0 && |
| 130 | - (dict_find_string(systemdict, "gserrordict", &perrordict) <= 0 || |
| 131 | - dict_find(perrordict, &error_name, &epref) <= 0)) |
| 132 | - ) |
| 133 | - return code; /* error name not in errordict??? */ |
| 134 | - } |
| 135 | + if (dict_find_string(systemdict, "gserrordict", &perrordict) <= 0 || |
| 136 | + (dict_find(perrordict, &error_name, &epref) <= 0 && |
| 137 | + (dict_find_string(systemdict, "errordict", &perrordict) <= 0 || |
| 138 | + dict_find(perrordict, &error_name, &epref) <= 0)) |
| 139 | + ) |
| 140 | + return code; /* error name not in errordict??? */ |
| 141 | + |
| 142 | doref = *epref; |
| 143 | epref = &doref; |
| 144 | /* Push the error object on the operand stack if appropriate. */ |
| 145 | @@ -695,6 +686,24 @@ again: |
| 146 | } |
| 147 | *osp = *perror_object; |
| 148 | errorexec_find(i_ctx_p, osp); |
| 149 | + /* If using SAFER, hand a name object to the error handler, rather than the executable |
| 150 | + * object/operator itself. |
| 151 | + */ |
| 152 | + if (i_ctx_p->LockFilePermissions) { |
| 153 | + code = obj_cvs(imemory, osp, buf + 2, 256, &rlen, (const byte **)&bufptr); |
| 154 | + if (code < 0) { |
| 155 | + const char *unknownstr = "--unknown--"; |
| 156 | + rlen = strlen(unknownstr); |
| 157 | + memcpy(buf, unknownstr, rlen); |
| 158 | + } |
| 159 | + else { |
| 160 | + buf[0] = buf[1] = buf[rlen + 2] = buf[rlen + 3] = '-'; |
| 161 | + rlen += 4; |
| 162 | + } |
| 163 | + code = name_ref(imemory, buf, rlen, osp, 1); |
| 164 | + if (code < 0) |
| 165 | + make_null(osp); |
| 166 | + } |
| 167 | } |
| 168 | goto again; |
| 169 | } |
| 170 | -- |
| 171 | 2.7.4 |
| 172 | |