From 98ab5c5770d20b39bf3c58083f31f31838f2e940 Mon Sep 17 00:00:00 2001 From: Hongxu Jia Date: Mon, 5 Nov 2018 16:03:37 +0800 Subject: ghostscript: fix CVE-2018-18284 Artifex Ghostscript 9.25 and earlier allows attackers to bypass a sandbox protection mechanism via vectors involving the 1Policy operator. Signed-off-by: Hongxu Jia Signed-off-by: Richard Purdie --- ...put-unavailable-from-.policyprocs-helper-.patch | 245 +++++++++++++++++++++ .../ghostscript/ghostscript_9.25.bb | 1 + 2 files changed, 246 insertions(+) create mode 100644 meta/recipes-extended/ghostscript/files/0008-Make-.forceput-unavailable-from-.policyprocs-helper-.patch (limited to 'meta/recipes-extended') diff --git a/meta/recipes-extended/ghostscript/files/0008-Make-.forceput-unavailable-from-.policyprocs-helper-.patch b/meta/recipes-extended/ghostscript/files/0008-Make-.forceput-unavailable-from-.policyprocs-helper-.patch new file mode 100644 index 0000000000..7cc51629ed --- /dev/null +++ b/meta/recipes-extended/ghostscript/files/0008-Make-.forceput-unavailable-from-.policyprocs-helper-.patch @@ -0,0 +1,245 @@ +From 9096beaa4451c12dd2a2caf000658fbac4a5bcdf Mon Sep 17 00:00:00 2001 +From: Ken Sharp +Date: Mon, 5 Nov 2018 15:51:32 +0800 +Subject: [PATCH] Make .forceput unavailable from '.policyprocs' helper + dictionary + +Bug #69963 "1Policy is a dangerous operator, any callers should be odef" + +Leaving the .policyprocs dictionary with a procedure which is a simple +wrapper for .forceput effectively leaves .forceput available. + +It seems that the only reason to have .policyprocs is to minimise the +code in .applypolicies, so we can remove the dictionary and put the +code straight into .applypolicies, which we can then bind and make +executeonly, which hides the .forceput. Also, since we don't need +.applypolicies after startup, we can undefine that from systemdict too. + +While we're here, review all the uses of .force* to make certain that +there are no other similar cases. This showed a few places where we +hadn't made a function executeonly, so do that too. Its probably not +required, since I'm reasonably sure its impossible to load those +functions as packed arrays (they are all defined as operators), but lets +have a belt and braces approach, the additional time cost is negligible. + +CVE: CVE-2018-18284 +Upstream-Status: Backport [git://git.ghostscript.com/ghostpdl.git] + +Signed-off-by: Hongxu Jia +--- + Resource/Init/gs_diskn.ps | 2 +- + Resource/Init/gs_dps.ps | 2 +- + Resource/Init/gs_epsf.ps | 2 +- + Resource/Init/gs_fonts.ps | 4 +- + Resource/Init/gs_init.ps | 2 +- + Resource/Init/gs_setpd.ps | 100 ++++++++++++++++++++++++---------------------- + 6 files changed, 58 insertions(+), 54 deletions(-) + +diff --git a/Resource/Init/gs_diskn.ps b/Resource/Init/gs_diskn.ps +index 26ec0b5..fd694bc 100644 +--- a/Resource/Init/gs_diskn.ps ++++ b/Resource/Init/gs_diskn.ps +@@ -61,7 +61,7 @@ systemdict begin + % doesn't get run enough to justify the complication + //.putdevparams + //systemdict /.searchabledevs .forceundef +-} .bind odef % must be bound and hidden for .forceundef ++} .bind executeonly odef % must be bound and hidden for .forceundef + + % ------ extend filenameforall to handle wildcards in %dev% part of pattern -------% + /filenameforall { +diff --git a/Resource/Init/gs_dps.ps b/Resource/Init/gs_dps.ps +index daf7b0f..00c14d5 100644 +--- a/Resource/Init/gs_dps.ps ++++ b/Resource/Init/gs_dps.ps +@@ -124,7 +124,7 @@ + /savedinitialgstate .systemvar setgstate gsave + % Wrap up. + end .setglobal +-} odef ++} bind executeonly odef + + % Check whether an object is a procedure. + /.proccheck { % .proccheck +diff --git a/Resource/Init/gs_epsf.ps b/Resource/Init/gs_epsf.ps +index e4037d9..2d0f677 100644 +--- a/Resource/Init/gs_epsf.ps ++++ b/Resource/Init/gs_epsf.ps +@@ -31,7 +31,7 @@ + /EPSBoundingBoxState 5 def + /EPSBoundingBoxSetState { + //systemdict /EPSBoundingBoxState 3 -1 roll .forceput +-} .bind odef % .forceput must be bound and hidden ++} .bind executeonly odef % .forceput must be bound and hidden + + % Parse 4 numbers for a bounding box + /EPSBoundingBoxParse { % (llx lly urx ury) -- llx lly urx ury true OR false +diff --git a/Resource/Init/gs_fonts.ps b/Resource/Init/gs_fonts.ps +index 72feff2..803faca 100644 +--- a/Resource/Init/gs_fonts.ps ++++ b/Resource/Init/gs_fonts.ps +@@ -583,7 +583,7 @@ buildfontdict 3 /.buildfont3 cvx put + } bind def + /.setloadingfont { + //systemdict /.loadingfont 3 -1 roll .forceput +-} .bind odef % .forceput must be bound and hidden ++} .bind executeonly odef % .forceput must be bound and hidden + /.loadfont + { % Some buggy fonts leave extra junk on the stack, + % so we have to make a closure that records the stack depth +@@ -1012,7 +1012,7 @@ $error /SubstituteFont { } put + dup length string copy + .forceput setglobal + } ifelse +-} .bind odef % must be bound and hidden for .forceput ++} .bind executeonly odef % must be bound and hidden for .forceput + + % Attempt to load a font from a file. + /.tryloadfont { % .tryloadfont true +diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps +index f4c1053..07ee968 100644 +--- a/Resource/Init/gs_init.ps ++++ b/Resource/Init/gs_init.ps +@@ -2230,7 +2230,7 @@ SAFER { .setsafeglobal } if + /.localvmarray /.localvmdict /.localvmpackedarray /.localvmstring /.systemvmarray /.systemvmdict /.systemvmpackedarray /.systemvmstring /.systemvmfile /.systemvmlibfile + /.systemvmSFD /.settrapparams /.currentsystemparams /.currentuserparams /.getsystemparam /.getuserparam /.setsystemparams /.setuserparams + /.checkpassword /.locale_to_utf8 /.currentglobal /.gcheck /.imagepath +- /.type /.writecvs /.setSMask /.currentSMask /.countexecstack /.execstack ++ /.type /.writecvs /.setSMask /.currentSMask /.countexecstack /.execstack /.applypolicies + + % Used by a free user in the Library of Congress. Apparently this is used to + % draw a partial page, which is then filled in by the results of a barcode +diff --git a/Resource/Init/gs_setpd.ps b/Resource/Init/gs_setpd.ps +index afb4ffa..7c076ad 100644 +--- a/Resource/Init/gs_setpd.ps ++++ b/Resource/Init/gs_setpd.ps +@@ -609,6 +609,23 @@ NOMEDIAATTRS { + % and we replace the key in the dictionary with its prior value + % (or remove it if it had no prior value). + ++% These procedures are called with the following on the stack: ++% ++% They are expected to consume the top 2 operands. ++% NOTE: we currently treat all values other than 0, 1, or 7 (for PageSize) ++% the same as 0, i.e., we signal an error. ++/0Policy { % Set errorinfo and signal a configurationerror. ++ NOMEDIAATTRS { ++ % NOMEDIAATTRS means that the default policy is 7... ++ pop 2 index exch 7 put ++ } { ++ pop dup 4 index exch get 2 array astore ++ $error /errorinfo 3 -1 roll put ++ cleartomark ++ /setpagedevice .systemvar /configurationerror signalerror ++ } ifelse ++} bind executeonly odef ++ + % Making this an operator means we can properly hide + % the contents - specifically .forceput + /1Policy +@@ -617,59 +634,46 @@ NOMEDIAATTRS { + SETPDDEBUG { (Rolling back.) = pstack flush } if + 3 index 2 index 3 -1 roll .forceput + 4 index 1 index .knownget +- { 4 index 3 1 roll .forceput } +- { 3 index exch .undef } ++ { 4 index 3 1 roll .forceput } ++ { 3 index exch .undef } + ifelse + } bind executeonly odef + +-/.policyprocs mark +-% These procedures are called with the following on the stack: +-% +-% They are expected to consume the top 2 operands. +-% NOTE: we currently treat all values other than 0, 1, or 7 (for PageSize) +-% the same as 0, i.e., we signal an error. +-% +-% M. Sweet, Easy Software Products: +-% +-% Define NOMEDIAATTRS to turn off the default (but unimplementable) media +-% selection policies for setpagedevice. This is used by CUPS to support +-% the standard Adobe media attributes. +- 0 { % Set errorinfo and signal a configurationerror. +- NOMEDIAATTRS { +- % NOMEDIAATTRS means that the default policy is 7... +- pop 2 index exch 7 put +- } { +- pop dup 4 index exch get 2 array astore +- $error /errorinfo 3 -1 roll put +- cleartomark +- /setpagedevice .systemvar /configurationerror signalerror +- } ifelse +- } bind +- 1 /1Policy load +- 7 { % For PageSize only, just impose the request. +- 1 index /PageSize eq +- { pop pop 1 index /PageSize 7 put } +- { .policyprocs 0 get exec } +- ifelse +- } bind +-.dicttomark readonly def +-currentdict /1Policy undef ++/7Policy { % For PageSize only, just impose the request. ++ 1 index /PageSize eq ++ { pop pop 1 index /PageSize 7 put } ++ { .policyprocs 0 get exec } ++ ifelse ++} bind executeonly odef + + /.applypolicies % .applypolicies + % +- { 1 index /Policies get 1 index +- { type /integertype eq +- { pop % already processed +- } +- { 2 copy .knownget not { 1 index /PolicyNotFound get } if +- % Stack: +- % +- .policyprocs 1 index .knownget not { .policyprocs 0 get } if exec +- } +- ifelse +- } +- forall pop +- } bind def ++{ ++ 1 index /Policies get 1 index ++ { type /integertype eq ++ { ++ pop % already processed ++ }{ ++ 2 copy .knownget not { 1 index /PolicyNotFound get } if ++ % Stack: ++ % ++ dup 1 eq { ++ 1Policy ++ }{ ++ dup 7 eq { ++ 7Policy ++ }{ ++ 0Policy ++ } ifelse ++ } ifelse ++ } ifelse ++ } ++ forall pop ++} bind executeonly odef ++ ++currentdict /0Policy undef ++currentdict /1Policy undef ++currentdict /7Policy undef + + % Prepare to present parameters to the device, by spreading them onto the + % operand stack and removing any that shouldn't be presented. +@@ -1006,7 +1010,7 @@ SETPDDEBUG { (Installing.) = pstack flush } if + .postinstall + } ifelse + setglobal % return to original VM allocation mode +-} odef ++} bind executeonly odef + + % We break out the code after calling the Install procedure into a + % separate procedure, since it is executed even if Install causes an error. +-- +2.7.4 + diff --git a/meta/recipes-extended/ghostscript/ghostscript_9.25.bb b/meta/recipes-extended/ghostscript/ghostscript_9.25.bb index 28521f3c4b..fdca8a2ac9 100644 --- a/meta/recipes-extended/ghostscript/ghostscript_9.25.bb +++ b/meta/recipes-extended/ghostscript/ghostscript_9.25.bb @@ -32,6 +32,7 @@ SRC_URI_BASE = "https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/d file://0005-Bug-699938-.loadfontloop-must-be-an-operator.patch \ file://0006-Undefine-some-additional-internal-operators.patch \ file://0007-Bug-699927-don-t-include-operator-arrays-in-execstac.patch \ + file://0008-Make-.forceput-unavailable-from-.policyprocs-helper-.patch \ " SRC_URI = "${SRC_URI_BASE} \ -- cgit 1.2.3-korg