| From 1f9a91c86bd56acf57826b9b0e020ebe1953e2ae Mon Sep 17 00:00:00 2001 |
| From: Chris Liddell <chris.liddell@artifex.com> |
| Date: Thu, 4 Oct 2018 10:42:13 +0100 |
| Subject: [PATCH 3/5] Bug 699832: add control over hiding error handlers. |
| |
| With a previous commit changing error handling in SAFER so the handler gets |
| passed a name object (rather than executable object), it is less critical to |
| hide the error handlers. |
| |
| This introduces a -dSAFERERRORS option to force only use of the default error |
| handlers. |
| |
| It also adds a .setsafererrors Postscript call, meaning a caller, without |
| -dSAFERERRORS, can create their own default error handlers (in errordict, as |
| normal), and then call .setsafererrors meaning their own handlers are always |
| called. |
| |
| With -dSAFERERRORS or after a call to .setsafererrors, .setsafererrors is |
| removed. |
| |
| CVE: CVE-2018-17961 |
| Upstream-Status: Backport [git://git.ghostscript.com/ghostpdl.git] |
| Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com> |
| --- |
| Resource/Init/gs_init.ps | 42 +++++++++++++++++++++++++++++------------ |
| psi/interp.c | 49 ++++++++++++++++++++++++++++-------------------- |
| 2 files changed, 59 insertions(+), 32 deletions(-) |
| |
| diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps |
| index bec307d..f952f32 100644 |
| --- a/Resource/Init/gs_init.ps |
| +++ b/Resource/Init/gs_init.ps |
| @@ -188,6 +188,16 @@ currentdict /DELAYSAFER known { /DELAYSAFER //true def /NOSAFER //true def } if |
| currentdict /PARANOIDSAFER known or % PARANOIDSAFER is equivalent |
| } |
| ifelse def |
| + |
| +/SAFERERRORS |
| +currentdict /NOSAFERERRORS known |
| +{ |
| + //false |
| +} |
| +{ |
| + currentdict /SAFERERRORS known |
| +} ifelse def |
| + |
| currentdict /SHORTERRORS known /SHORTERRORS exch def |
| currentdict /TTYPAUSE known /TTYPAUSE exch def |
| currentdict /WRITESYSTEMDICT known /WRITESYSTEMDICT exch def |
| @@ -1123,12 +1133,23 @@ errordict begin |
| } bind def |
| end % errordict |
| |
| -% Put all the default handlers in gserrordict |
| -gserrordict |
| -errordict {2 index 3 1 roll put} forall |
| -noaccess pop |
| -% remove the non-standard errors from errordict |
| +gserrordict /unknownerror errordict /unknownerror get put |
| errordict /unknownerror .undef |
| + |
| +/.SAFERERRORLIST ErrorNames def |
| +/.setsafererrors |
| +{ |
| +% Put all the requested handlers in gserrordict |
| + gserrordict |
| + //.SAFERERRORLIST |
| + {dup errordict exch get 2 index 3 1 roll put} forall |
| + noaccess pop |
| + systemdict /.setsafeerrors .forceundef |
| + systemdict /.SAFERERRORLIST .forceundef |
| +} bind executeonly odef |
| + |
| +SAFERERRORS {.setsafererrors} if |
| + |
| % Define a stable private copy of handleerror that we will always use under |
| % JOBSERVER mode. |
| /.GShandleerror errordict /handleerror get def |
| @@ -1760,18 +1781,15 @@ currentdict /.runlibfile .undef |
| |
| % Bind all the operators defined as procedures. |
| /.bindoperators % binds operators in currentdict |
| - { % Temporarily disable the typecheck error. |
| - errordict /typecheck 2 copy get |
| - errordict /typecheck { pop } put % pop the command |
| + { |
| currentdict |
| { dup type /operatortype eq |
| - { % This might be a real operator, so bind might cause a typecheck, |
| - % but we've made the error a no-op temporarily. |
| - .bind |
| + { |
| + % This might be a real operator, so bind might cause a typecheck |
| + {.bind} .internalstopped pop |
| } |
| if pop pop |
| } forall |
| - put |
| } def |
| DELAYBIND not { .bindoperators } if |
| |
| diff --git a/psi/interp.c b/psi/interp.c |
| index 3dd5f7a..cd894f9 100644 |
| --- a/psi/interp.c |
| +++ b/psi/interp.c |
| @@ -662,27 +662,18 @@ again: |
| if (gs_errorname(i_ctx_p, code, &error_name) < 0) |
| return code; /* out-of-range error code! */ |
| |
| - /* If LockFilePermissions is true, we only refer to gserrordict, which |
| - * is not accessible to Postcript jobs |
| + /* We refer to gserrordict first, which is not accessible to Postcript jobs |
| + * If we're running with SAFERERRORS all the handlers are copied to gserrordict |
| + * so we'll always find the default one. If not SAFERERRORS, only gs specific |
| + * errors are in gserrordict. |
| */ |
| - if (i_ctx_p->LockFilePermissions) { |
| - if (((dict_find_string(systemdict, "gserrordict", &perrordict) <= 0 || |
| - dict_find(perrordict, &error_name, &epref) <= 0)) |
| - ) |
| - return code; /* error name not in errordict??? */ |
| - } |
| - else { |
| - /* |
| - * For greater Adobe compatibility, only the standard PostScript errors |
| - * are defined in errordict; the rest are in gserrordict. |
| - */ |
| - if (dict_find_string(systemdict, "errordict", &perrordict) <= 0 || |
| - (dict_find(perrordict, &error_name, &epref) <= 0 && |
| - (dict_find_string(systemdict, "gserrordict", &perrordict) <= 0 || |
| - dict_find(perrordict, &error_name, &epref) <= 0)) |
| - ) |
| - return code; /* error name not in errordict??? */ |
| - } |
| + if (dict_find_string(systemdict, "gserrordict", &perrordict) <= 0 || |
| + (dict_find(perrordict, &error_name, &epref) <= 0 && |
| + (dict_find_string(systemdict, "errordict", &perrordict) <= 0 || |
| + dict_find(perrordict, &error_name, &epref) <= 0)) |
| + ) |
| + return code; /* error name not in errordict??? */ |
| + |
| doref = *epref; |
| epref = &doref; |
| /* Push the error object on the operand stack if appropriate. */ |
| @@ -695,6 +686,24 @@ again: |
| } |
| *osp = *perror_object; |
| errorexec_find(i_ctx_p, osp); |
| + /* If using SAFER, hand a name object to the error handler, rather than the executable |
| + * object/operator itself. |
| + */ |
| + if (i_ctx_p->LockFilePermissions) { |
| + code = obj_cvs(imemory, osp, buf + 2, 256, &rlen, (const byte **)&bufptr); |
| + if (code < 0) { |
| + const char *unknownstr = "--unknown--"; |
| + rlen = strlen(unknownstr); |
| + memcpy(buf, unknownstr, rlen); |
| + } |
| + else { |
| + buf[0] = buf[1] = buf[rlen + 2] = buf[rlen + 3] = '-'; |
| + rlen += 4; |
| + } |
| + code = name_ref(imemory, buf, rlen, osp, 1); |
| + if (code < 0) |
| + make_null(osp); |
| + } |
| } |
| goto again; |
| } |
| -- |
| 2.7.4 |
| |