Andrew Geissler | 99467da | 2019-02-25 18:54:23 -0600 | [diff] [blame] | 1 | From 5c49efe24dda0f2dbd2a09b9159e683cce99b6d8 Mon Sep 17 00:00:00 2001 |
| 2 | From: Chris Liddell <chris.liddell@artifex.com> |
| 3 | Date: Fri, 11 Jan 2019 13:36:36 +0000 |
| 4 | Subject: [PATCH 7/7] Remove .forcedef, and harden .force* ops more |
| 5 | |
| 6 | Remove .forcedef and replace all uses with a direct call to .forceput instead. |
| 7 | |
| 8 | Ensure every procedure (named and trasient) that calls .forceput is |
| 9 | executeonly. |
| 10 | |
| 11 | CVE: CVE-2019-6116 |
| 12 | Upstream-Status: Backport [git://git.ghostscript.com/ghostpdl.git] |
| 13 | |
| 14 | Signed-off-by: Ovidiu Panait <ovidiu.panait@windriver.com> |
| 15 | --- |
| 16 | Resource/Init/gs_dps1.ps | 15 +++++++----- |
| 17 | Resource/Init/gs_init.ps | 28 ++++++++------------- |
| 18 | Resource/Init/gs_lev2.ps | 51 +++++++++++++++++++-------------------- |
| 19 | Resource/Init/gs_ll3.ps | 5 ++-- |
| 20 | Resource/Init/gs_res.ps | 29 +++++++++++----------- |
| 21 | Resource/Init/gs_statd.ps | 4 +-- |
| 22 | 6 files changed, 63 insertions(+), 69 deletions(-) |
| 23 | |
| 24 | diff --git a/Resource/Init/gs_dps1.ps b/Resource/Init/gs_dps1.ps |
| 25 | index 8700c8c..3d2cf7a 100644 |
| 26 | --- a/Resource/Init/gs_dps1.ps |
| 27 | +++ b/Resource/Init/gs_dps1.ps |
| 28 | @@ -33,14 +33,17 @@ systemdict begin |
| 29 | |
| 30 | /SharedFontDirectory .FontDirectory .gcheck |
| 31 | { .currentglobal //false .setglobal |
| 32 | + currentdict |
| 33 | /LocalFontDirectory .FontDirectory dup maxlength dict copy |
| 34 | - .forcedef % LocalFontDirectory is local, systemdict is global |
| 35 | + .forceput % LocalFontDirectory is local, systemdict is global |
| 36 | .setglobal .FontDirectory |
| 37 | - } |
| 38 | - { /LocalFontDirectory .FontDirectory |
| 39 | - .forcedef % LocalFontDirectory is local, systemdict is global |
| 40 | + } executeonly |
| 41 | + { |
| 42 | + currentdict |
| 43 | + /LocalFontDirectory .FontDirectory |
| 44 | + .forceput % LocalFontDirectory is local, systemdict is global |
| 45 | 50 dict |
| 46 | - } |
| 47 | + }executeonly |
| 48 | ifelse def |
| 49 | |
| 50 | end % systemdict |
| 51 | @@ -55,7 +58,7 @@ level2dict begin |
| 52 | { //SharedFontDirectory } |
| 53 | { /LocalFontDirectory .systemvar } % can't embed ref to local VM |
| 54 | ifelse .forceput pop % LocalFontDirectory is local, systemdict is global |
| 55 | - } .bind odef |
| 56 | + } .bind executeonly odef |
| 57 | % Don't just copy (load) the definition of .setglobal: |
| 58 | % it gets redefined for LL3. |
| 59 | /setshared { /.setglobal .systemvar exec } odef |
| 60 | diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps |
| 61 | index d9a0829..45bebf4 100644 |
| 62 | --- a/Resource/Init/gs_init.ps |
| 63 | +++ b/Resource/Init/gs_init.ps |
| 64 | @@ -54,7 +54,7 @@ systemdict exch |
| 65 | dup /userdict |
| 66 | currentdict dup 200 .setmaxlength % userdict |
| 67 | .forceput % userdict is local, systemdict is global |
| 68 | - } |
| 69 | + } executeonly |
| 70 | if begin |
| 71 | |
| 72 | % Define dummy local/global operators if needed. |
| 73 | @@ -299,13 +299,6 @@ QUIET not { printgreeting flush } if |
| 74 | 1 index exch .makeoperator def |
| 75 | } .bind def |
| 76 | |
| 77 | -% Define a special version of def for storing local objects into global |
| 78 | -% dictionaries. Like .forceput, this exists only during initialization. |
| 79 | -/.forcedef { % <key> <value> .forcedef - |
| 80 | - 1 .argindex pop % check # of args |
| 81 | - currentdict 3 1 roll .forceput |
| 82 | -} .bind odef |
| 83 | - |
| 84 | % Define procedures for accessing variables in systemdict and userdict |
| 85 | % regardless of the contents of the dictionary stack. |
| 86 | /.systemvar { % <name> .systemvar <value> |
| 87 | @@ -347,7 +340,7 @@ DELAYBIND |
| 88 | } |
| 89 | ifelse |
| 90 | } .bind def |
| 91 | -} if |
| 92 | +} executeonly if |
| 93 | |
| 94 | %**************** BACKWARD COMPATIBILITY **************** |
| 95 | /hwsizedict mark /HWSize //null .dicttomark readonly def |
| 96 | @@ -655,7 +648,7 @@ currentdict /.typenames .undef |
| 97 | /ifelse .systemvar |
| 98 | ] cvx executeonly |
| 99 | exch .setglobal |
| 100 | -} odef |
| 101 | +} executeonly odef |
| 102 | systemdict /internaldict dup .makeinternaldict .makeoperator |
| 103 | .forceput % proc is local, systemdict is global |
| 104 | |
| 105 | @@ -1093,7 +1086,7 @@ def |
| 106 | |
| 107 | % Define $error. This must be in local VM. |
| 108 | .currentglobal //false .setglobal |
| 109 | -/$error 40 dict .forcedef % $error is local, systemdict is global |
| 110 | +currentdict /$error 40 dict .forceput % $error is local, systemdict is global |
| 111 | % newerror, errorname, command, errorinfo, |
| 112 | % ostack, estack, dstack, recordstacks, |
| 113 | % binary, globalmode, |
| 114 | @@ -1112,8 +1105,8 @@ end |
| 115 | % Define errordict similarly. It has one entry per error name, |
| 116 | % plus handleerror. However, some astonishingly badly written PostScript |
| 117 | % files require it to have at least one empty slot. |
| 118 | -/errordict ErrorNames length 3 add dict |
| 119 | -.forcedef % errordict is local, systemdict is global |
| 120 | +currentdict /errordict ErrorNames length 3 add dict |
| 121 | +.forceput % errordict is local, systemdict is global |
| 122 | .setglobal % back to global VM |
| 123 | % gserrordict contains all the default error handling methods, but unlike |
| 124 | % errordict it is noaccess after creation (also it is in global VM). |
| 125 | @@ -1273,8 +1266,9 @@ end |
| 126 | (END PROCS) VMDEBUG |
| 127 | |
| 128 | % Define the font directory. |
| 129 | +currentdict |
| 130 | /FontDirectory //false .setglobal 100 dict //true .setglobal |
| 131 | -.forcedef % FontDirectory is local, systemdict is global |
| 132 | +.forceput % FontDirectory is local, systemdict is global |
| 133 | |
| 134 | % Define the encoding dictionary. |
| 135 | /EncodingDirectory 16 dict def % enough for Level 2 + PDF standard encodings |
| 136 | @@ -2333,7 +2327,6 @@ SAFER { .setsafeglobal } if |
| 137 | //systemdict /UndefinePostScriptOperators get exec |
| 138 | //systemdict /UndefinePDFOperators get exec |
| 139 | //systemdict /.forcecopynew .forceundef % remove temptation |
| 140 | - //systemdict /.forcedef .forceundef % ditto |
| 141 | //systemdict /.forceput .forceundef % ditto |
| 142 | //systemdict /.undef .forceundef % ditto |
| 143 | //systemdict /.forceundef .forceundef % ditto |
| 144 | @@ -2368,9 +2361,9 @@ SAFER { .setsafeglobal } if |
| 145 | % (and, if implemented, context switching). |
| 146 | .currentglobal //false .setglobal |
| 147 | mark userparams { } forall .dicttomark readonly |
| 148 | - /userparams exch .forcedef % systemdict is read-only |
| 149 | + currentdict exch /userparams exch .forceput % systemdict is read-only |
| 150 | .setglobal |
| 151 | -} if |
| 152 | +} executeonly if |
| 153 | /.currentsystemparams where { |
| 154 | pop |
| 155 | % Remove real system params from pssystemparams. |
| 156 | @@ -2458,7 +2451,6 @@ end |
| 157 | DELAYBIND not { |
| 158 | systemdict /.bindnow .undef % We only need this for DELAYBIND |
| 159 | systemdict /.forcecopynew .undef % remove temptation |
| 160 | - systemdict /.forcedef .undef % ditto |
| 161 | systemdict /.forceput .undef % ditto |
| 162 | systemdict /.forceundef .undef % ditto |
| 163 | } if |
| 164 | diff --git a/Resource/Init/gs_lev2.ps b/Resource/Init/gs_lev2.ps |
| 165 | index 0f0d573..9c0c3a6 100644 |
| 166 | --- a/Resource/Init/gs_lev2.ps |
| 167 | +++ b/Resource/Init/gs_lev2.ps |
| 168 | @@ -304,31 +304,30 @@ end |
| 169 | psuserparams exch /.checkFilePermitparams load put |
| 170 | .setglobal |
| 171 | |
| 172 | -pssystemparams begin |
| 173 | - /CurDisplayList 0 .forcedef |
| 174 | - /CurFormCache 0 .forcedef |
| 175 | - /CurInputDevice () .forcedef |
| 176 | - /CurOutlineCache 0 .forcedef |
| 177 | - /CurOutputDevice () .forcedef |
| 178 | - /CurPatternCache 0 .forcedef |
| 179 | - /CurUPathCache 0 .forcedef |
| 180 | - /CurScreenStorage 0 .forcedef |
| 181 | - /CurSourceList 0 .forcedef |
| 182 | - /DoPrintErrors //false .forcedef |
| 183 | - /JobTimeout 0 .forcedef |
| 184 | - /LicenseID (LN-001) .forcedef % bogus |
| 185 | - /MaxDisplayList 140000 .forcedef |
| 186 | - /MaxFormCache 100000 .forcedef |
| 187 | - /MaxImageBuffer 524288 .forcedef |
| 188 | - /MaxOutlineCache 65000 .forcedef |
| 189 | - /MaxPatternCache 100000 .forcedef |
| 190 | - /MaxUPathCache 300000 .forcedef |
| 191 | - /MaxScreenStorage 84000 .forcedef |
| 192 | - /MaxSourceList 25000 .forcedef |
| 193 | - /PrinterName product .forcedef |
| 194 | - /RamSize 4194304 .forcedef |
| 195 | - /WaitTimeout 40 .forcedef |
| 196 | -end |
| 197 | +pssystemparams |
| 198 | +dup /CurDisplayList 0 .forceput |
| 199 | +dup /CurFormCache 0 .forceput |
| 200 | +dup /CurInputDevice () .forceput |
| 201 | +dup /CurOutlineCache 0 .forceput |
| 202 | +dup /CurOutputDevice () .forceput |
| 203 | +dup /CurPatternCache 0 .forceput |
| 204 | +dup /CurUPathCache 0 .forceput |
| 205 | +dup /CurScreenStorage 0 .forceput |
| 206 | +dup /CurSourceList 0 .forceput |
| 207 | +dup /DoPrintErrors //false .forceput |
| 208 | +dup /JobTimeout 0 .forceput |
| 209 | +dup /LicenseID (LN-001) .forceput % bogus |
| 210 | +dup /MaxDisplayList 140000 .forceput |
| 211 | +dup /MaxFormCache 100000 .forceput |
| 212 | +dup /MaxImageBuffer 524288 .forceput |
| 213 | +dup /MaxOutlineCache 65000 .forceput |
| 214 | +dup /MaxPatternCache 100000 .forceput |
| 215 | +dup /MaxUPathCache 300000 .forceput |
| 216 | +dup /MaxScreenStorage 84000 .forceput |
| 217 | +dup /MaxSourceList 25000 .forceput |
| 218 | +dup /PrinterName product .forceput |
| 219 | +dup /RamSize 4194304 .forceput |
| 220 | + /WaitTimeout 40 .forceput |
| 221 | |
| 222 | % Define the procedures for handling comment scanning. The names |
| 223 | % %ProcessComment and %ProcessDSCComment are known to the interpreter. |
| 224 | @@ -710,7 +709,7 @@ pop % currentsystemparams |
| 225 | /statusdict currentdict def |
| 226 | |
| 227 | currentdict end |
| 228 | -/statusdict exch .forcedef % statusdict is local, systemdict is global |
| 229 | +currentdict exch /statusdict exch .forceput % statusdict is local, systemdict is global |
| 230 | |
| 231 | % The following compatibility operators are in systemdict. They are |
| 232 | % defined here, rather than in gs_init.ps, because they require the |
| 233 | diff --git a/Resource/Init/gs_ll3.ps b/Resource/Init/gs_ll3.ps |
| 234 | index c86721f..881af44 100644 |
| 235 | --- a/Resource/Init/gs_ll3.ps |
| 236 | +++ b/Resource/Init/gs_ll3.ps |
| 237 | @@ -521,9 +521,8 @@ end |
| 238 | % Define additional user and system parameters. |
| 239 | /HalftoneMode 0 .definepsuserparam |
| 240 | /MaxSuperScreen 1016 .definepsuserparam |
| 241 | -pssystemparams begin % read-only, so use .forcedef |
| 242 | - /MaxDisplayAndSourceList 160000 .forcedef |
| 243 | -end |
| 244 | +% read-only, so use .forceput |
| 245 | +pssystemparams /MaxDisplayAndSourceList 160000 .forceput |
| 246 | |
| 247 | % Define the IdiomSet resource category. |
| 248 | { /IdiomSet } { |
| 249 | diff --git a/Resource/Init/gs_res.ps b/Resource/Init/gs_res.ps |
| 250 | index b016113..89c0ed6 100644 |
| 251 | --- a/Resource/Init/gs_res.ps |
| 252 | +++ b/Resource/Init/gs_res.ps |
| 253 | @@ -41,10 +41,10 @@ level2dict begin |
| 254 | % However, Ed Taft of Adobe says their interpreters don't implement this |
| 255 | % either, so we aren't going to worry about it for a while. |
| 256 | |
| 257 | -currentglobal //false setglobal systemdict begin |
| 258 | - /localinstancedict 5 dict |
| 259 | - .forcedef % localinstancedict is local, systemdict is global |
| 260 | -end //true setglobal |
| 261 | +currentglobal //false setglobal |
| 262 | + systemdict /localinstancedict 5 dict |
| 263 | + .forceput % localinstancedict is local, systemdict is global |
| 264 | +//true setglobal |
| 265 | /.emptydict 0 dict readonly def |
| 266 | setglobal |
| 267 | |
| 268 | @@ -149,7 +149,7 @@ setglobal |
| 269 | dup [ exch 0 -1 ] exch |
| 270 | .Instances 4 2 roll put |
| 271 | % Make the Category dictionary read-only. We will have to |
| 272 | - % use .forceput / .forcedef later to replace the dummy, |
| 273 | + % use .forceput / .forceput later to replace the dummy, |
| 274 | % empty .Instances dictionary with the real one later. |
| 275 | readonly |
| 276 | }{ |
| 277 | @@ -304,7 +304,8 @@ systemdict begin |
| 278 | dup () ne { |
| 279 | .file_name_directory_separator concatstrings |
| 280 | } if |
| 281 | - 2 index exch //false .file_name_combine not { |
| 282 | + 2 index exch //false |
| 283 | + .file_name_combine not { |
| 284 | (Error: .default_resource_dir returned ) print exch print ( that can't combine with ) print = |
| 285 | /.default_resource_dir cvx /configurationerror signalerror |
| 286 | } if |
| 287 | @@ -317,14 +318,14 @@ currentdict /pssystemparams known not { |
| 288 | pssystemparams begin |
| 289 | //.default_resource_dir exec |
| 290 | /FontResourceDir (Font) //.resource_dir_name exec |
| 291 | - readonly .forcedef % pssys'params is r-o |
| 292 | + readonly currentdict 3 1 roll .forceput % pssys'params is r-o |
| 293 | /GenericResourceDir () //.resource_dir_name exec |
| 294 | - readonly .forcedef % pssys'params is r-o |
| 295 | + readonly currentdict 3 1 roll .forceput % pssys'params is r-o |
| 296 | pop % .default_resource_dir |
| 297 | /GenericResourcePathSep |
| 298 | - .file_name_separator readonly .forcedef % pssys'params is r-o |
| 299 | - (%diskFontResourceDir) cvn (/Resource/Font/) readonly .forcedef % pssys'params is r-o |
| 300 | - (%diskGenericResourceDir) cvn (/Resource/) readonly .forcedef % pssys'params is r-o |
| 301 | + .file_name_separator readonly currentdict 3 1 roll .forceput % pssys'params is r-o |
| 302 | + currentdict (%diskFontResourceDir) cvn (/Resource/Font/) readonly .forceput % pssys'params is r-o |
| 303 | + currentdict (%diskGenericResourceDir) cvn (/Resource/) readonly .forceput % pssys'params is r-o |
| 304 | end |
| 305 | end |
| 306 | |
| 307 | @@ -422,8 +423,8 @@ status { |
| 308 | .Instances dup //.emptydict eq { |
| 309 | pop 3 dict |
| 310 | % As noted above, Category dictionaries are read-only, |
| 311 | - % so we have to use .forcedef here. |
| 312 | - /.Instances 1 index .forcedef % Category dict is read-only |
| 313 | + % so we have to use .forceput here. |
| 314 | + currentdict /.Instances 2 index .forceput % Category dict is read-only |
| 315 | } executeonly if |
| 316 | } |
| 317 | { .LocalInstances dup //.emptydict eq |
| 318 | @@ -441,7 +442,7 @@ status { |
| 319 | { /defineresource cvx /typecheck signaloperror |
| 320 | } |
| 321 | ifelse |
| 322 | -} .bind executeonly .makeoperator % executeonly to prevent access to .forcedef |
| 323 | +} .bind executeonly .makeoperator % executeonly to prevent access to .forceput |
| 324 | /UndefineResource |
| 325 | { { dup 2 index .knownget |
| 326 | { dup 1 get 1 ge |
| 327 | diff --git a/Resource/Init/gs_statd.ps b/Resource/Init/gs_statd.ps |
| 328 | index 20d4c96..b6a7659 100644 |
| 329 | --- a/Resource/Init/gs_statd.ps |
| 330 | +++ b/Resource/Init/gs_statd.ps |
| 331 | @@ -21,10 +21,10 @@ systemdict begin |
| 332 | % We make statusdict a little larger for Level 2 stuff. |
| 333 | % Note that it must be allocated in local VM. |
| 334 | .currentglobal //false .setglobal |
| 335 | - /statusdict 91 dict .forcedef % statusdict is local, sys'dict global |
| 336 | + currentdict /statusdict 91 dict .forceput % statusdict is local, sys'dict global |
| 337 | % To support the Level 2 job control features, |
| 338 | % serverdict must also be in local VM. |
| 339 | - /serverdict 10 dict .forcedef % serverdict is local, sys'dict global |
| 340 | + currentdict /serverdict 10 dict .forceput % serverdict is local, sys'dict global |
| 341 | .setglobal |
| 342 | end |
| 343 | |
| 344 | -- |
| 345 | 2.18.1 |
| 346 | |