Fortunately, AppArmor comes with a local override facility. Let's use it to fix this error (which may be in
/var/log/audit.logdepending on how the system is set up):
kernel: [ 7226.358630] type=1400 audit(1416403573.247:17): apparmor="DENIED" operation="mknod" profile="/usr/sbin/tcpdump" name="/var/log/tcpdump/memcache-20141119-072608.pcap.gz" pid=2438 comm="gzip" requested_mask="c" denied_mask="c" fsuid=0 ouid=0
requested_mask="c"means the command (
comm="gzip") tried to create a file (given by the
namevalue) and AppArmor denied it. The profile tells us, indirectly, which AppArmor file caused the denial; substitute the first '/' with the AppArmor config dir (/etc/apparmor.d/) and the rest with dots. Thus, if we look in
/etc/apparmor.d/usr.sbin.tcpdump, we find the system policy. It has granted access to
*.pcapcase-insensitively anywhere in the system, with the rule
/**.[pP][cC][aA][pP] rw. I used that rule to choose my filename outside of $HOME, but now the
-z /bin/gzipparameter I used isn't able to do its work because it can't create the *.gz version there.
Incidentally, the command differs from the profile in this case, because tcpdump executed gzip. It's allowed to do that by the system profile, which uses
ixpermissions—that stands for inherit-execute, and means that the gzip command is run under the current AppArmor profile. All the permissions defined for tcpdump continue to affect the gzip command.
Anyway, back to that fix I promised. AppArmor provides
/etc/apparmor.d/local/for rules to add to the main ones. (Although this can't be used to override an explicit deny like tcpdump's ban on using files in
$HOME/bin.) We just need to add a rule for the *.gz, and while we're there, why not the *.bz2 version as well?
The trailing comma does not seem to be an issue for me. Note also that we don't need to specify the binary and braces, since the
#includeline in the system profile is already inside the braces.
Ubuntu ships some files in the local directory already; we should be able to run
sudo -e /etc/apparmor.d/local/usr.sbin.tcpdumpand add the lines above to the existing file. Once the file is ready, we need to reload that profile to the kernel. Note that we use the system profile here, not the one we just edited:
I'm not clear enough on how AppArmor works to know if we need to restart the service now (I'm purposely leaving my tcpdump service file/discussion out of this post) because I restarted mine just to be safe.
sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.tcpdump