0003-Bug-699832-add-control-over-hiding-error-handlers.patch 6.1 KB

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