AppArmor is a security framework for Linux which allows the administrator to define profiles for specific applications only. One application that immediately springs to mind is the web browser, since multiple security flaws have been found in any of these and a relatively fine-grained security system is necessary in order not to pose problems in usability and at the same time protect sensitive data (for example, you want your web browser to access at least one directory, such as $HOME/Desktop, while it doesn’t need any access to, say, $HOME/.ssh).
For brevity, I have removed all the license information from these files. Please refer to the license paragraph for more details.
Please note that very often, I allowed custom paths, such as $HOME/daten/im. These are unique to my system and you likely want to change/remove these lines.
AppArmor provides a relatively easy way to define abstractions and tunables. Think of them as default settings and aliases. However, the current state (early 2012) of AppArmor in Debian is…unsatisfactory, so I decided to put together both my own tunables and my own abstractions. The idea behind the latter was that stuff in /usr generally doesn’t need protection: I generally only confine processes running as users, not root (No, browsing as root is bad for you) and things in /usr are generally assumed to be easily publicly attainable. Yes, I agree that some sensitive information may escape that way (which programs did I install?), but I am willing to take that ‘risk’ in order to avoid having to track down each and every library my confined programs need.
I therefore put together these abstractions, placed in /etc/apparmor.d/abstractions/:
This global gives access to ‘harmless’ files and allows client programs to connect to X.
# Everybody can access /usr, /bin, /lib32, /lib64, /lib, {,var}/tmp in reading mode
/usr/ r,
/usr/** rmk,
/{,s}bin/ r,
/{,s}bin/** rmk,
/lib{,32,64}/ r,
/lib{,32,64}/** rmk,
/tmp/ r,
/var/tmp/ r,
# /dev
/dev/log w,
/dev/zero rw,
/dev/null rw,
/dev/full rw,
/dev/urandom r,
/dev/random r,
# Potentially problematic
/dev/dri/** rw,
# /proc
@{PROC}/sys/kernel/version r,
@{PROC}/sys/kernel/ngroups_max r,
@{PROC}/sys/kernel/osrelease r,
@{PROC}/sys/kernel/ostype r,
@{PROC}/sys/kernel/pid_max r,
@{PROC}/meminfo r,
@{PROC}/stat r,
@{PROC}/cpuinfo r,
@{PROC}/filesystems r,
@{PROC}/proc/uptime r,
@{PROC}/version r,
owner @{PROC}/*/maps r,
owner @{PROC}/*/mountinfo r,
owner @{PROC}/*/cmdline r,
owner @{PROC}/*/stat r,
# /sys
/sys/devices/system/cpu/ r,
# /etc
/etc/localtime rm,
/etc/bindresvport.blacklist rm,
/etc/default/locale rm,
/etc/ld.so.cache rm,
/etc/X11/cursors/ r,
/etc/X11/cursors/** rm,
/etc/magic r,
/etc/mailcap rk,
/etc/mime.types r,
# Programs to run in confined mode
/bin/dash ix,
/bin/grep ix,
/bin/ps ix,
/bin/uname ix,
/usr/bin/file ix,
/bin/sed ix,
/bin/which ix,
/bin/readlink ix,
/usr/bin/dirname ix,
# Known bad files
deny /etc/locale.alias r,
This allows an application to access all the fonts saved in the various places on my system. Some configuration files are also necessary here.
/etc/ghostscript/fontmap.d/ r,
/etc/ghostscript/fontmap.d/** rm,
/etc/X11/fonts/ r,
/etc/X11/fonts/** rm,
/etc/fonts/ r,
/etc/fonts/** rm,
owner @{HOME}/.fonts.conf rm,
owner @{HOME}/.fonts/ r,
owner @{HOME}/.fonts/** rm,
owner @{HOME}/.fontconfig r,
owner @{HOME}/.fontconfig/** rmwl,
/var/cache/fonts/ r,
/var/cache/fonts/** rm,
/var/cache/fontconfig r,
/var/cache/fontconfig/** rml,
/var/lib/ghostscript/** rm,
/var/lib/defoma/** rm,
/datapub/media/fonts/ r,
/datapub/media/fonts/** rm,
Some applications might want to connect to dbus. This is also potentially risky.
/usr/bin/dbus-launch ix,
/var/lib/dbus/machine-id r,
/{,var/}run/dbus/system_bus_socket w,
Some files in /dev are necessary to play audio:
# /dev
/dev/audio* rwm,
/dev/dsp* rwm,
/dev/mixer* rwm,
/dev/sequencer rwm,
/dev/sequencer2 rwm,
/dev/snd/* rwm,
@{PROC}/asound/** rwm,
# libcanberra
@{HOME}/.cache/event-sound-cache.* rwk,
# libgnome2
/etc/sound/ r,
/etc/sound/** r,
In order to be able to draw nice file-saving dialogs and do some other magic stuff, applications might need access to these files:
# Access rights to provide smooth file dialogs and common files for graphical interfaces
owner @{HOME}/.icons/ r,
owner @{HOME}/.icons/** r,
owner @{HOME}/.local/share/** rk,
owner @{HOME}/.themes/** r,
owner @{HOME}/.local/share/recently-used.xbel* rwmk,
owner @{HOME}/.config/gtk-2.0/gtkfilechooser.ini* r,
owner @{HOME}/.config/user-dirs.dirs rk,
owner @{HOME}/.config/Trolltech.conf rmk,
owner @{HOME}/.gtkrc-2.0 rm,
owner @{HOME}/.gtk-bookmarks r,
owner @{HOME}/.gtk-custom-papers rwmk,
owner @{HOME}/.ICEauthority rm,
owner @{HOME}/.Xauthority rm,
owner @{HOME}/.xsession-errors rwm,
owner @{HOME}/.mailcap rwmk,
owner /tmp/.X11-unix/* w,
/tmp/orbit-*/ rw,
/tmp/orbit-*/** rw,
Browsers must be allowed to do some networking.
network inet dgram,
network inet stream,
network inet6 dgram,
network inet6 stream,
/etc/default/nss rm,
/etc/group rm,
/etc/host.conf rm,
/etc/hosts rm,
/etc/nsswitch.conf rm,
/etc/gai.conf rm,
/etc/passwd rm,
/etc/protocols rm,
/etc/services rm,
/etc/resolv.conf rm,
/proc/*/net/route rm,
Finally, I want Pidgin to be able to launch my browser:
/usr/bin/opera Pix,
/usr/bin/opera-next Pix,
/usr/lib/iceweasel/iceweasel Pix,
It might also be feasible to define a few ‘aliases’:
@{HOME}=@{HOMEDIRS}/*/ /root/
@{HOMEDIRS}=/home/
@{multiarch}=*-linux-gnu*
@{PROC}=/proc/
Creating the profile for Opera is then pretty straight-forward. Note that with this profile, Opera is not allowed to launch external programs, such as a PDF viewer (apart from my mail client, Claws-Mail). I did this because I didn’t want to define all such programs one by one, and using some sort of wrapper (like xdg-open, exo-open etc.) was also not an option: Try what happens when you run exo-open on any of your *.desktop files: It will happily execute whatever it says in the Exec= line. Which is kind of sub-optimal, unless you want to run these programs also in a confined mode.
The profile is as follows:
#include <tunables/global>
/usr/bin/opera {
#include <abstractions/audio>
#include <abstractions/global>
#include <abstractions/fonts>
#include <abstractions/networking>
#include <abstractions/interface>
/etc/operaprefs_default.ini rk,
/etc/operaprefs_fixed.ini rk,
/usr/bin/claws-mail PUx,
owner @{HOME}/.adobe/Flash_Player/ r,
owner @{HOME}/.adobe/Flash_Player/** rkw,
owner @{HOME}/.gstreamer-0.10/* r,
owner @{HOME}/.cups/lpoptions r,
owner @{HOME}/.mozilla/firefox/** r,
owner @{HOME}/.opera/ r,
owner @{HOME}/.opera/** rwk,
owner @{HOME}/Desktop/ r,
owner @{HOME}/Desktop/** rwk,
owner /tmp/gtkprint** rwk,
owner /tmp/orcexec.* rwmk,
owner /tmp/*.ps rwmk,
owner /tmp/*.oex rwmk,
/usr/bin/opera rix,
/usr/lib/opera/opera rix,
/usr/lib/opera/operaplugincleaner rix,
/usr/lib/opera/operapluginwrapper rix,
/usr/lib/opera/operapluginwrapper-native rix,
/usr/lib/gstreamer0.10/gstreamer-0.10/gst-plugin-scanner rix,
owner /var/tmp/crash* wrk,
}
Opera Next wants to access slightly different paths:
#include <tunables/global>
/usr/bin/opera-next {
#include <abstractions/audio>
#include <abstractions/global>
#include <abstractions/fonts>
#include <abstractions/networking>
#include <abstractions/interface>
/etc/operaprefs_default.ini rk,
/etc/operaprefs_fixed.ini rk,
/usr/bin/claws-mail PUx,
owner @{HOME}/.adobe/Flash_Player/ r,
owner @{HOME}/.adobe/Flash_Player/** rkw,
owner @{HOME}/.gstreamer-0.10/* r,
owner @{HOME}/.cups/lpoptions r,
owner @{HOME}/.mozilla/firefox/** r,
owner @{HOME}/.opera-next/ r,
owner @{HOME}/.opera-next/** rwk,
owner @{HOME}/Desktop/ r,
owner @{HOME}/Desktop/** rwk,
owner /tmp/gtkprint** rwk,
owner /tmp/orcexec.* rwmk,
owner /tmp/*.ps rwmk,
owner /tmp/*.oex rwmk,
/usr/bin/opera-next rix,
/usr/lib/opera-next/opera-next rix,
/usr/lib/opera-next/operaplugincleaner rix,
/usr/lib/opera-next/operapluginwrapper rix,
/usr/lib/opera-next/operapluginwrapper-native rix,
/usr/lib/gstreamer0.10/gstreamer-0.10/gst-plugin-scanner rix,
/usr/lib/opera-next/** rix,
owner /var/tmp/crash* wrk,
/proc/*/fd/ r,
}
The profile for Pidgin is relatively straightforward. I did not test it with video/voice calls, so it might require some further help in this regard.
#include <tunables/global>
/usr/bin/pidgin {
#include <abstractions/audio>
#include <abstractions/global>
#include <abstractions/fonts>
#include <abstractions/networking>
#include <abstractions/interface>
#include <abstractions/start-browser>
capability sys_ptrace,
/etc/python2.7/sitecustomize.py r,
/etc/wildmidi/wildmidi.cfg r,
owner @{HOME}/.purple/ r,
owner @{HOME}/.purple/** rwkm,
owner @{HOME}/Desktop/ r,
owner @{HOME}/Desktop/** rwk,
owner @{HOME}/daten/im/ r,
owner @{HOME}/daten/im/** rwk,
owner @{HOME}/.gstreamer-0.10/registry.x86_64.bin rm,
owner /tmp/orcexec.* rwmk,
}
Skype is a little bit odd, as it wants to mmap practically everything and refuses to make calls without knowing the kernel’s version number (now included in abstractions/global)…
#include <tunables/global>
/usr/bin/skype {
#include <abstractions/audio>
#include <abstractions/global>
#include <abstractions/fonts>
#include <abstractions/networking>
#include <abstractions/interface>
#include <abstractions/start-browser>
/dev/ r,
/dev/video* mrw,
owner @{HOME}/Desktop/ r,
owner @{HOME}/Desktop/** rwk,
owner @{HOME}/.Skype/ rw,
owner @{HOME}/.Skype/** krw,
}
For brevity, I have removed the license information from the ‘files’ above. If you want to distribute them, please add the following header to these code snippets and obey the terms dictated within them.
# Copyright 2011, 2012 Claudius Hubig <info@chubig.net>. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# THIS SOFTWARE IS PROVIDED BY CLAUDIUS HUBIG "AS IS" AND ANY EXPRESS
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL CLAUDIUS HUBIG OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.