Bugzilla – Bug 1065388
apparmor is breaking tool file in lessopen.sh
Last modified: 2023-02-28 20:45:02 UTC
Tracing lessopen.sh with export LESS_ADVANCED_PREPROCESSOR=yes shows [...] ++ file -L ./less.1 + type='./less.1: writable, regular file, no read permission' but it should be noether less/less-487> file -L ./less.1 ./less.1: troff or preprocessor input, ASCII text in /etc/apparmor.d/usr.bin.lessopen.sh I found /usr/bin/file rix, but no rule for /usr/bin/file its self! All tools listed in /etc/apparmor.d/usr.bin.lessopen.sh should be able to read files as otherwise nothings goes.
And as root I'm not allowed to read via less and lessopen.sh + echo /usr/src/werner/less/less-487/less.1 + grep -q '^/' + SRC=/usr/src/werner/less/less-487/less.1 + NAME=less.1 + '[' '!' -r /usr/src/werner/less/less-487/less.1 ']' + exit 1 ... which is in lessopen.sh if echo "$1" | grep -q ^/; then # absolute path SRC="$1" else # relative path SRC="./$1" fi NAME="${SRC##*/}" [ ! -r "$SRC" ] && exit 1 ... this is not what should it be IMHO
Can you please - switch the profile into complain/learning mode: aa-complain /etc/apparmor.d/usr.bin.lessopen.sh - repeat the previously forbidden/failing things - complain mode means to allow everything and log what would be denied, so everything should work now - attach your /var/log/audit/audit.log (if you don't have auditd running, syslog, journal or dmesg output are alternatives - grep for "apparmor") - finally switch the profile back to enforce mode aa-enforce /etc/apparmor.d/usr.bin.lessopen.sh As an alternative, you can also run aa-logprof to update the profile yourself. In this case, please tell me which rules you needed to add.
Created attachment 746170 [details] /var/log/audit/audit.log (In reply to Christian Boltz from comment #2) > Can you please > - switch the profile into complain/learning mode: > aa-complain /etc/apparmor.d/usr.bin.lessopen.sh > - repeat the previously forbidden/failing things - complain mode means to > allow > everything and log what would be denied, so everything should work now > - attach your /var/log/audit/audit.log (if you don't have auditd running, > syslog, > journal or dmesg output are alternatives - grep for "apparmor") > - finally switch the profile back to enforce mode > aa-enforce /etc/apparmor.d/usr.bin.lessopen.sh > > As an alternative, you can also run aa-logprof to update the profile > yourself. In this case, please tell me which rules you needed to add. Here we are
Hmmm ... I do not see the `/usr/bin/file' command in the audit.log ... do I something miss here? The groff and co commands are there
type=AVC msg=audit(1509089056.461:3242): apparmor="DENIED" operation="sendmsg" profile="/usr/bin/lessopen.sh" pid=11880 comm="file" lport=911 family="inet" sock_type="dgram" protocol=17 type=AVC msg=audit(1509104771.741:3298): apparmor="ALLOWED" operation="sendmsg" profile="/usr/bin/lessopen.sh" pid=24929 comm="file" lport=911 family="inet" sock_type="dgram" protocol=17 ... Hmmm ... what does this mean?
Thanks for the log! To get your major issue solved, please add capability dac_read_search, capability dac_override, to the profile and reload it with rcapparmor reload. This is needed to allow root to read files and enter directories owned by a user with for example -rwx------ permissions. With AppArmor confinement, root needs these two capabilities to override the missing read permissions. (See capabilities(7) for more details.) There are some more denials in your log (looks like groff executes several helper binaries) which I'll check later. (In reply to Dr. Werner Fink from comment #0) > in /etc/apparmor.d/usr.bin.lessopen.sh I found > > /usr/bin/file rix, > > but no rule for /usr/bin/file its self! The "ix" in the rule means "inherit", so /usr/bin/file will run under the same profile as lessopen.sh. (In reply to Dr. Werner Fink from comment #5) > type=AVC msg=audit(1509089056.461:3242): apparmor="DENIED" > operation="sendmsg" profile="/usr/bin/lessopen.sh" pid=11880 comm="file" > lport=911 family="inet" sock_type="dgram" protocol=17 > > ... Hmmm ... what does this mean? Let me guess - you tried to view a file on a NFS share? Ideally this should be hidden in the kernel so that the application doesn't see the network access (because that's on the filesystem level). I know there's an open bugreport about this - I'll check with upstream if/when we can expect a kernel patch.
Hmmm ... now the errors are reversed: As usaer I see (with -x in /usr/bin/lessopen.sh and both with LESS_ADVANCED_PREPROCESSOR=yes + echo less.1 + grep -q '^/' + SRC=./less.1 + NAME=less.1 + '[' '!' -r ./less.1 ']' + exit 1 and as root + echo /usr/src/werner/less/less-487/less.1 + grep -q '^/' + SRC=/usr/src/werner/less/less-487/less.1 + NAME=less.1 + '[' '!' -r /usr/src/werner/less/less-487/less.1 ']' + trap cleaner EXIT SIGHUP ++ mktemp /tmp/less.XXXXXXXXX + TMPF=/tmp/less.fHJaeD4Yy ++ mktemp /tmp/less.XXXXXXXXX + TMPF_pre=/tmp/less.lySv6TnKu + lang=POSIX + test -n '' + case "$lang" in + GROFF_DEVICE=latin1 + CMD= ++ /usr/bin/file -L /usr/src/werner/less/less-487/less.1 + type='/usr/src/werner/less/less-487/less.1: regular file, no read permission' + case ${type#"$SRC": } in + rm -f /tmp/less.lySv6TnKu + TMPF_pre=/usr/src/werner/less/less-487/less.1 + test -n '' ++ /usr/bin/file -L /usr/src/werner/less/less-487/less.1 + type='/usr/src/werner/less/less-487/less.1: regular file, no read permission' + case ${type#"$TMPF_pre": } in + '[' yes = yes ']' + case ${type#"$TMPF_pre": } in + rm -f /tmp/less.fHJaeD4Yy + TMPF=/usr/src/werner/less/less-487/less.1 + test /usr/src/werner/less/less-487/less.1 = /usr/src/werner/less/less-487/less.1 + cleaner + test /usr/src/werner/less/less-487/less.1 = /usr/src/werner/less/less-487/less.1 -o /usr/src/werner/less/less-487/less.1 = /usr/src/werner/less/less-487/less.1 + return
Comment the two lines out and now I see as User + echo less.1 + grep -q '^/' + SRC=./less.1 + NAME=less.1 + '[' '!' -r ./less.1 ']' + trap cleaner EXIT SIGHUP ++ mktemp /tmp/less.XXXXXXXXX + TMPF=/tmp/less.xPGl3RPNK ++ mktemp /tmp/less.XXXXXXXXX + TMPF_pre=/tmp/less.7U86wilju + lang=POSIX + test -n de_DE.UTF-8 + lang=de_DE.UTF-8 + case "$lang" in + GROFF_DEVICE=utf8 + CMD= ++ /usr/bin/file -L ./less.1 + type='./less.1: writable, regular file, no read permission' + case ${type#"$SRC": } in + rm -f /tmp/less.7U86wilju + TMPF_pre=./less.1 + test -n '' ++ /usr/bin/file -L ./less.1 + type='./less.1: writable, regular file, no read permission' + case ${type#"$TMPF_pre": } in + '[' yes = yes ']' + case ${type#"$TMPF_pre": } in + rm -f /tmp/less.xPGl3RPNK + TMPF=./less.1 + test ./less.1 = ./less.1 + cleaner + test ./less.1 = ./less.1 -o ./less.1 = ./less.1 + return and as root + echo /usr/src/werner/less/less-487/less.1 + grep -q '^/' + SRC=/usr/src/werner/less/less-487/less.1 + NAME=less.1 + '[' '!' -r /usr/src/werner/less/less-487/less.1 ']' + exit 1
with network inet dgram, network inet stream, network unix dgram, network unix stream, the file command returns the corect identifier in both user abd toot case ++ /usr/bin/file -L ./less.1 + type='./less.1: troff or preprocessor input, ASCII text' ++ /usr/bin/file -L /usr/src/werner/less/less-487/less.1 + type='/usr/src/werner/less/less-487/less.1: troff or preprocessor input, ASCII text' but now groff is not allowed to read the file and return am empty output
root: + groff -s -p -t -e -Tlatin1 -mandoc /usr/src/werner/less/less-487/less.1 + ls -l /tmp/less.A57j2Hy6s -rw------- 1 root root 0 Oct 27 18:57 /tmp/less.A57j2Hy6s useer: + ls -l /tmp/less.AhSUBYMWC -rw------- 1 werner suse 0 Oct 27 18:57 /tmp/less.AhSUBYMWC user direct call: groff -s -p -t -e -Tutf8 -mandoc ./less.1 | wc -c 84173
Heere wa are + groff -s -p -t -e -Tlatin1 -mandoc /usr/src/werner/less/less-487/less.1 groff: couldn't exec soelim: Permission denied groff: couldn't exec tbl: Permission denied groff: couldn't exec troff: Permission denied groff: couldn't exec pic: Permission denied groff: couldn't exec grotty: Permission denied groff: couldn't exec eqn: Permission denied
Created attachment 746218 [details] /etc/apparmor.d/usr.bin.lessopen.sh With this it seems to work but I do not have tested all cases
The trick is to mention network connections used for sendmsg as well as the exeuctable used by groff and ps2ascii ... maybe there are more around
Created attachment 746220 [details] updated /etc/apparmor.d/usr.bin.lessopen.sh profile OK, here we go. Let me start with the easy part: As you noticed, groff wants to execute several helper binaries: operation="exec" name="/usr/bin/eqn" comm="groff" operation="exec" name="/usr/bin/grotty" comm="groff" operation="exec" name="/usr/bin/pic" comm="groff" operation="exec" name="/usr/bin/soelim" comm="groff" operation="exec" name="/usr/bin/tbl" comm="groff" operation="exec" name="/usr/bin/troff" comm="groff" All listed binaries somehow belong to groff (according to a quick look at their manpage), so that's fine and means to add the following rules to the profile: /usr/bin/eqn mrix, /usr/bin/grotty mrix, /usr/bin/id mrix, /usr/bin/pic mrix, /usr/bin/soelim mrix, /usr/bin/tbl mrix, /usr/bin/troff mrix, and of course also the two rules from my previous comment: capability dac_override, capability dac_read_search, The attached profile contains these additions. Please replace /etc/apparmor.d/usr.bin.lessopen.sh with this and run "rcapparmor reload" afterwards. (The profile is in enforce mode, and I intentionally didn't add the network permissions and the things noted below yet, so you might need to use aa-complain again.) You might also want to run old /var/log/audit/audit.log rcauditd restart to start with an empty audit.log. Now the interesting[tm] questions start: ... operation="exec" profile="/usr/bin/lessopen.sh" name="/usr/bin/id" pid=32146 comm="lessopen.sh" requested_mask="x" denied_mask="x" fsuid=223 ouid=0 so lessopen.sh wants to execute "id" - but I don't see any "id" call in my Tumbleweed lessopen.sh. Do you have a different lessopen.sh, or am I just blind? (Allowing to run "id" doesn't look like a serious security issue (especially because the profile already allows reading everything including /proc/self/status) - but of course it should only be allowed if it's really needed.) And finally, there is (before you switched the profile into complain mode): type=AVC msg=audit(1509081678.576:3010): apparmor="DENIED" operation="unlink" profile="/usr/bin/lessopen.sh" name="/usr/bin/lessopen.sh" pid=30470 comm="rm" requested_mask="d" denied_mask="d" fsuid=0 ouid=0 So for some reason lessopen.sh tried to delete itsself (by calling "rm") this morning :-/ The exact time is: # date -d @1509081678 # the number after msg=audit is the unix timestamp Fr 27. Okt 07:21:18 CEST 2017 Any idea which of the "rm" commands in lessopen.sh did this? Checking your (root) bash history for that timestamp might should which file you wanted to view at that time, and that might make debugging easier. (In reply to Dr. Werner Fink from comment #9) > with > > network inet dgram, > network inet stream, > network unix dgram, > network unix stream, > > the file command returns the corect identifier in both user abd toot case The two "network unix" streams are only needed until AppArmor 2.11.1 reaches Tumbleweed - there was a a bugfix in apparmor_parser which only showed up in combination with kernel 4.14 rc2 and newer. (Dominique just accepted the staging project, so it should be in one of the next snapshots.) The two "network inet" rules are probably related to NFS - I'm still waiting for an answer from upstream.
That's what I get for rewording my text - let me fix two errors... (In reply to Christian Boltz from comment #14) > Any idea which of the "rm" commands in lessopen.sh did this? Checking your > (root) bash history for that timestamp might should which file you wanted to s/might should/should show/ > The two "network unix" streams are only needed until AppArmor 2.11.1 reaches > Tumbleweed - there was a a bugfix in apparmor_parser which only showed up in s/only showed up/is only needed/
(In reply to Christian Boltz from comment #14) > > ... operation="exec" profile="/usr/bin/lessopen.sh" name="/usr/bin/id" > pid=32146 comm="lessopen.sh" requested_mask="x" denied_mask="x" fsuid=223 > ouid=0 > > so lessopen.sh wants to execute "id" - but I don't see any "id" call in my > Tumbleweed lessopen.sh. Do you have a different lessopen.sh, or am I just > blind? (Allowing to run "id" doesn't look like a serious security issue > (especially because the profile already allows reading everything including > /proc/self/status) - but of course it should only be allowed if it's really > needed.) > This id call was added for debugging only as I've checked out which which id for lessopen.sh is used if less is used by root > > And finally, there is (before you switched the profile into complain mode): > > type=AVC msg=audit(1509081678.576:3010): apparmor="DENIED" > operation="unlink" profile="/usr/bin/lessopen.sh" > name="/usr/bin/lessopen.sh" pid=30470 comm="rm" requested_mask="d" > denied_mask="d" fsuid=0 ouid=0 > > So for some reason lessopen.sh tried to delete itsself (by calling "rm") > this morning :-/ The exact time is: > # date -d @1509081678 # the number after msg=audit is the unix timestamp > Fr 27. Okt 07:21:18 CEST 2017 Bug in my test code, fixed > (In reply to Dr. Werner Fink from comment #9) > > with > > > > network inet dgram, > > network inet stream, > > network unix dgram, > > network unix stream, > > > > the file command returns the corect identifier in both user abd toot case > > The two "network unix" streams are only needed until AppArmor 2.11.1 reaches > Tumbleweed - there was a a bugfix in apparmor_parser which only showed up in > combination with kernel 4.14 rc2 and newer. (Dominique just accepted the > staging project, so it should be in one of the next snapshots.) > > The two "network inet" rules are probably related to NFS - I'm still waiting > for an answer from upstream.
(In reply to Christian Boltz from comment #14) > As you noticed, groff wants to execute several helper binaries: > operation="exec" name="/usr/bin/eqn" comm="groff" > operation="exec" name="/usr/bin/grotty" comm="groff" > operation="exec" name="/usr/bin/pic" comm="groff" > operation="exec" name="/usr/bin/soelim" comm="groff" > operation="exec" name="/usr/bin/tbl" comm="groff" > operation="exec" name="/usr/bin/troff" comm="groff" That seems the perfect case or an abstraction .. that is that we migth think about a file gorff below /etc/apparmor.d/abstractions/ which includes those lines? Beside this the line /usr/bin/id mrix, should be removed as this was for debugging only: > All listed binaries somehow belong to groff (according to a quick look at > their manpage), so that's fine and means to add the following rules to the > profile: > > /usr/bin/eqn mrix, > /usr/bin/grotty mrix, > /usr/bin/id mrix, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > /usr/bin/pic mrix, > /usr/bin/soelim mrix, > /usr/bin/tbl mrix, > /usr/bin/troff mrix,
Created attachment 746246 [details] proposed /etc/apparmor.d/abstractions/groff What do you think about this? Similar we could to for man command and this abstraction is useful for man comand
I filled bsc#1206957 where `less` complains about: /usr/share/lmod/8.7.15/init/bash: line 57: /usr/bin/readlink: Permission denied /usr/share/lmod/8.7.15/init/bash: line 61: /usr/bin/expr: Permission denied /usr/share/lmod/8.7.15/init/bash: line 62: /usr/bin/basename: Permission denied At the beginning I thought that this was related with lmod, but after checking the audit log I saw: type=AVC msg=audit(1673254728.860:235): apparmor="DENIED" operation="exec" profile="/usr/bin/lessopen.sh" name="/usr/bin/readlink" pid=6441 comm="lessopen.sh" requested_mask="x" denied_mask="x" fsuid=1000 ouid=0 type=AVC msg=audit(1673254728.860:236): apparmor="DENIED" operation="exec" profile="/usr/bin/lessopen.sh" name="/usr/bin/expr" pid=6442 comm="lessopen.sh" requested_mask="x" denied_mask="x" fsuid=1000 ouid=0 type=AVC msg=audit(1673254728.860:237): apparmor="DENIED" operation="exec" profile="/usr/bin/lessopen.sh" name="/usr/bin/basename" pid=6443 comm="lessopen.sh" requested_mask="x" denied_mask="x" fsuid=1000 ouid=0 So I wonder if this will require some extension on the lessopen.sh profile?
(In reply to Alberto Planas Dominguez from comment #19) > I filled bsc#1206957 where `less` complains about: > > /usr/share/lmod/8.7.15/init/bash: line 57: /usr/bin/readlink: Permission > denied > /usr/share/lmod/8.7.15/init/bash: line 61: /usr/bin/expr: Permission denied > /usr/share/lmod/8.7.15/init/bash: line 62: /usr/bin/basename: Permission > denied > > At the beginning I thought that this was related with lmod, but after > checking the audit log I saw: > > type=AVC msg=audit(1673254728.860:235): apparmor="DENIED" operation="exec" > profile="/usr/bin/lessopen.sh" name="/usr/bin/readlink" pid=6441 > comm="lessopen.sh" requested_mask="x" denied_mask="x" fsuid=1000 ouid=0 > type=AVC msg=audit(1673254728.860:236): apparmor="DENIED" operation="exec" > profile="/usr/bin/lessopen.sh" name="/usr/bin/expr" pid=6442 > comm="lessopen.sh" requested_mask="x" denied_mask="x" fsuid=1000 ouid=0 > type=AVC msg=audit(1673254728.860:237): apparmor="DENIED" operation="exec" > profile="/usr/bin/lessopen.sh" name="/usr/bin/basename" pid=6443 > comm="lessopen.sh" requested_mask="x" denied_mask="x" fsuid=1000 ouid=0 > > So I wonder if this will require some extension on the lessopen.sh profile? That looks like a problem with usr merge
*** Bug 1206957 has been marked as a duplicate of this bug. ***
That other bug is not a duplicate and has nothing to do with usrmerge. It's just very nasty what lmod does. lmod installs /etc/profile.d/lmod.sh which sources /usr/share/lmod/8.7.15/init/bash. That in turn defines all kinds of random things. I suppose that script gets executed every single time a shell is launched, which might be the case when lessopen.sh starts. That is basically impossible to catch with apparmor. Messing with the shell like that should be verboten in any case IMO.
Comments 19..22 are handled in bug 1206957 - please ignore them here since this bugreport is already long enough. Actually I wonder - is there anything left in this old bugreport or can we close it? The only remaining thing I noticed are the comments 17 and 18. They include the idea of creating abstractions/groff with lots of '/usr/bin/$whatever mrix,' rules. In upstream AppArmor, we tend to avoid execute rules in abstractions (because it makes using other execute modes like Px hard), therefore I'm not sure if I like your idea. OTOH, having an abstraction with all the groff helpers looks useful. Maybe a solution would be to _only_ allow executing all the helpers, but not groff and nroff itsself so that people could still run groff or nroff with Px or Cx, and then include the abstraction in that separate profile. Werner, since the proposed abstraction is quite old, can you please have a quick look at it if the list of helpers is still up-to-date before I finally submit it upstream?
(In reply to Christian Boltz from comment #23) > > Werner, since the proposed abstraction is quite old, can you please have a > quick look at it if the list of helpers is still up-to-date before I finally > submit it upstream? Please replace the /usr/lib/groff/** with /usr/libexec/groff/** in the attachment https://bugzilla.opensuse.org/attachment.cgi?id=746246
Created attachment 863963 [details] Proposed /etc/apparmor.d/abstractions/groff with corrected libexe entry (In reply to Dr. Werner Fink from comment #24) > (In reply to Christian Boltz from comment #23) > > > > Werner, since the proposed abstraction is quite old, can you please have a > > quick look at it if the list of helpers is still up-to-date before I finally > > submit it upstream? > > Please replace the /usr/lib/groff/** with /usr/libexec/groff/** > in the attachment https://bugzilla.opensuse.org/attachment.cgi?id=746246
Thanks for the updated abstraction! I submitted it upstream: https://gitlab.com/apparmor/apparmor/-/merge_requests/973
This is an autogenerated message for OBS integration: This bug (1065388) was mentioned in https://build.opensuse.org/request/show/1068312 Factory / apparmor