AppArmor and Upstart
jamie at canonical.com
Wed Dec 21 19:52:07 UTC 2011
(Please keep me in CC, I am not subscribed to the list. CC'ing Kees as
well, since he did most of the existing work on this.)
James asked me to send something to the list on why AppArmor is not
currently converted to upstart in Ubuntu.
== Background ==
AppArmor is a Mandatory Access Control (MAC) system for Linux, and is
used extensively in Ubuntu. It consists of an administrator or
distribution defined policy for specified binaries. The policy is
defined in human-readable text files in /etc/apparmor.d. This
human-readable policy is compiled and loaded into the kernel via the
apparmor_parser command. For policy to be in effect for a binary, the
policy for that binary must be loaded into the kernel prior to the
binary's execution. Policy can be reloaded with the new policy put into
effect during runtime if the binary already has policy attached to it
(ie, it started after policy was loaded for it). Depending on the policy
being compiled, it can take up to several seconds to compile the policy
then load it into the kernel. Policy must be compiled anew when the
policy or the kernel changes. To improve boot speed, binary caches of
the compiled policy are used in Ubuntu (/etc/apparmor.d/cache) and the
binary policy is loaded into the kernel as fast as the cache can be read
from disk. Updating of the cache happens automatically after
== Current State ==
Currently in Ubuntu, policy load happens in 2 stages:
1. within the job of an upstartified package (eg cups)
2. via the SysV initscript (/etc/init.d/apparmor) which is required for
packages that have AppArmor policy, but not a job file (eg evince)
For upstartified packages with an apparmor profile, the job file must
load the AppArmor policy prior to execution of the confined binary (see
above). As a convenience, the /lib/init/apparmor-profile-load helper is
provided to simplify upstart integration.
For packages that ship policy but do not have a job file, policy must be
loaded sometime before application launch, which is why stage 2 is
needed. Stage 2 will (re)load all policy.
On Ubuntu, in both stage 1 and stage 2, binary caches are used unless it
is determined that policy must be recompiled (eg, booting a new
Some applications are corner cases, like dhclient. Because it needs to
have its policy loaded extremely earlier in the boot process, the
network-interface-security.conf is used to ensure this happens.
== Considerations ==
* the second stage reloads policy that may have already been loaded in
stage 1. In practice, this is not a problem because not that much policy
is loaded in upstart jobs and the reload of policy is always done using
the cache (since stage 1 will update the cache automatically as needed).
* there is a race condition between when the apparmor SysV initscript
runs and when people might be using applications (ie, there is no
guarantee that /etc/init.d/apparmor will run before a user starts
evince). In practice, this does not tend to happen
* people enabling the apparmor-profiles package that use policy that
confines applications with upstart jobs do not have the policy loaded
via the upstart jobs. Classic example is smbd. This can be fixed in the
apparmor-profiles package by also shipping an upstart job to load the
profile (or via the samba packaging, like with avahi)
* people defining new policy for applications with upstart jobs need to
not only create the policy, but update the upstart job to load it. This
is not easily discoverable, and a pain point for administrators
Due to concerns with boot speed, it was decided that this policy load
should not happen during early boot, but rather 'as late as possible'.
The use of binary caches helped significantly here, but policy is
recompiled on the first boot of a new kernel and loading policy early
will delay time to login screen by several seconds or more.
== Going forward ==
This has been discussed many times.
The status quo works 'ok' at the distribution level. If we ship policy
for an upstartified application, then we adjust the job accordingly. The
dhclient corner case is well tested, and the SysV initscript works well
enough in practice. There is still the theoretical race condition as
well as the non-discoverability for the administrator.
Perhaps the best solution is for the kernel to send a notification to
userspace on exec (ie, something upstart could use) and userspace would
load policy on demand. This would eliminate all race conditions and any
need for loading policy in individual jobs. Updating the kernel in this
manner seemed both intrusive and a performance bottleneck and was deemed
We could make the apparmor helper for upstart an integral part of
Upstart such that when a job is started, Upstart automatically loads
policy for the executable. This is an interesting option, but seems to
require considerable work. It solves the non-discoverability problem as
well as time on distribution integration work, but does not obviate the
need for the second stage.
We could move the second stage to upstart. This could work but it
doesn't solve the non-discoverability problem and due to the
event-driven nature of Upstart, it is not clear how this job would be
declared such that it happens after early boot but before login (any
type of login-- lightdm, gdm, kdm, console, etc, etc). Depending on how
this is done, it may end up being a lot of work to end up basically
where we are now with the SysV initscript.
So, in a nutshell, while improvements can be made, it is not clear that
the effort involved improves the situation enough to justify it. I could
of course be missing something. :)
Hope this helps!
Jamie Strandboge | http://www.canonical.com
-------------- next part --------------
A non-text attachment was scrubbed...
Size: 836 bytes
Desc: This is a digitally signed message part
More information about the upstart-devel