[apparmor] Apparmor with initramfs mode
john.johansen at canonical.com
Mon Jun 30 08:22:09 UTC 2014
On 06/30/2014 03:09 AM, Francois Bussery wrote:
> I’m using apparmor on an embedded system based on initramfs.
> Unfortunately, I have noticed that the files in the initramfs are not checked by apparmor.
> Has somebody already worked on that topic?
yes, but it is some what problematic, and requires manual setup at the moment. It is not
a configuration that we have examples for or is even currently a focus but it has been
done. You need policy, and a loader or the policy compiler in the initramfs, and you need
to mount sysfs, and securityfs in the initramfs.
The mounts aren't really a big deal as they can be remounted again later so that they
show up in the right place when the real root is mounted. And since they are virtual
filesystems that are built in to the kernel there is no dependency or race issues to
deal with. So the only thing you really need to do is modify the initramfs scripts to
Managing policy is a bit more of a problem. Obviously you need to copy the policy into
the initramfs when it is created. Generally you don't want to be compiling policy in
the initramfs so what you want is the cached binary policy, and you need a loader.
We don't have a standalone loader atm, but the parser will do it if passed the -B
flag. If you want you can also copy in the policy source files as well but be careful
to make sure that the timestamps are earlier than that of the parsers, as the parser
uses that to check in the the policy source files are newer than the cache files,
which can trigger a compile.
To load the policy modify your initramfs scripts to call the parser with the policy
to be loaded. You can then even unmount security and sysfs if you want.
You can then continue with regular booting, once out of the initramfs you can even
reload policy or and more policy. Generally the idea is to have only what is required
in the initramfs because it is costly (relative to regular boot time) to copy/load
data out of the initramfs, and because policy can very easily break your boot if it
is not fully developed.
Now to compiling policy for the initramfs. The easiest way is to boot into the kernel
you want to load policy for and have the parser compile the policy and store it to
a cache. You can then copy the cached files into the initramfs when you build it.
AppArmor policy is somewhat tied to the kernel and compiler (apparmor_parser) in that
the parser will compile certain features based on what the kernel advertises as being
available. However newer kernels do support and accept policy from older userspaces
so even if the policy is built for an older kernel, or with an older userspace it
should work. If you are doing a direct load using the -B the caching checks for
policy matching to the kernel are not done and older policy can be loaded, which
means you can get away with not having to update your initramfs everytime you update
policy, especially if you do a secondary policy load that may have extra/newer policy.
So currently it is doable, it just requires some manual tweaking of the initramfs.
There are improvements in the works that will help some in the future (primarily
better caching, support for multiple kernel versions in cache, and splitting the
parser into a library so there can be a separate loader).
There is also the currently experimental feature on the dev kernels that allows you
to set a boot/init profile that starts in unconfined mode, and can then be replaced
early in boot to provide total system confinement without having to do all the
extra that policy in the initramfs requires. Of course it won't meet everyones needs
but for those it does its easier than mucking with the initramfs.
More information about the AppArmor