24 Apparmorbinarypolicy
John Johansen edited this page 2018-07-28 02:04:08 +00:00

Warning this is a WIP

TOC

Introduction

In AppArmor 2.13, AppArmor moved from a policy caching scheme to a binary policy scheme. The binary policy scheme is still a form of caching of text policy but the layout and semantics have changed allowing for improvements that where not possible under the old caching scheme. Specifically

  • binary policy is assumed to exist at early kernel boot so the text policy does not need to be checked
  • binary policy exists for each kernel that is booted so there is no clearing of the "cache" when switching kernels
  • binary policy can be pre-shipped as immutable policy. With or without the corresponding text policy
  • binary policy can be a cache of locally modifiable text policy
  • binary policy allows for local updates against read-only images via an overlay system

With these changes policy can be shipped using traditional packaging or read-only images, and the init system can load policy from early boot with out having to do text policy compiles or consistency checks.

Management of binary policy

Building of the binary policy cache

Traditional packaging

Read-only images

Read-only images without a kernel

Kernels with the same feature abi

It is possible that different kernels may export the same apparmor feature abi. This is not a problem from AppArmor's perspective as the binary policy cache will work the same for these kernels. This can however present a problem for package management systems.

To deal with this package management systems are allowed to use unreserved dot files to keep track of which kernels the binary policy is being shared by. The suggested scheme is to use symlinks back to the respective kernel directories.

??? or should it go to the modules dir

.kernel_4.14.0-24  -> /boot/vmlinuz-4.14.0-24
.kernel_4.15.0-12  -> /boot/vmlinuz-4.15.0-12

In systems where cleaning up the binary policy cache is not required (eg. read-only images) this additional tracking step is not needed.

Multiple policy directories

Some distributions may split policy into different directories. In this case different binary policy directory root must be defined for each policy location if there is any chance any of the text policy files in the different locations may have the same name.

If the distribution still wants to use the default recommended binary policy locations then an extra directory level can be added.

Eg.

$(location)/system/...
$(location)/snappy/...

Generally it is recommended that policy be compiled at installation time,. For traditional packaging this means building on the host, but for read-only images that include a kernel this means building policy as packages are being installed and the image is being build.

Layout of binary policy

Binary policy is laid out as a forest of directories under a primary directory tree at $(location). Under $(location) directory is set of directories with their names based off of a hash of the kernel feature abi set the policy was compiled for followed by a collision number.

$(location)/kernel_feature_hash.collison_number

For example

binarypolicy

In the above example 7f01cf2e is the hash of a kernel features abi, and the .0 collision number indicates that it is the first cache directory with the feature hash of 7f01cf2e. The 7f01cf2e.1 directory, is a directory with the same hash as 7f01cf2e.0 but a different kernel feature abi set, each directory contains the full feature set abi file to resolve any hash collisions.

Within each binary policy directory is laid out the same as the policy cache directory with .features file for the kernel feature set the binary policy was compile for, and a file per for each compiled text policy file. In the above example 7f01cf2e.0/bin.ping is the compiled binary policy file for the $(policy)/bing.ping text policy file compiled for a kernel who's feature abi hashes to 7f01cf2e. While a035ea11.0/bin.ping is a binary cache file for the same text policy file, $(policy)/bin/ping, but for a different kernel.

Note that binary policy cache files within the directory correspond to a given text policy file name.

Symlink files within the cache are used to map cache files that

Binary Policy Validity check

Binary policy is guaranteed to have at a minimum the same checks for validity done for the policy cache. That is the parser will check each files time stamp against the text policy time stamps during a compile.

In addition to the time stamp check, a feature comparison check is done, however unlike policy caching binary policy will not clear the cache if the features do not match, it will create a new subdirectory with an incremented revision number. ???? move to first check???

With the introduction of AppArmor 3.0 an addition policy hash check was added to ensure that the binary policy is valid.

Management of binary policy directories

  • directory is not removed/cleared when it doesn't match. New dir is created
  • left to package management to manage cleanup of dirs
  • Binary policy cache should be created before rebooting into new kernel

Loading policy

Because binary policy is no longer treated as a cache that is cleared it is assumed that a binary policy cache will exist at boot. This means that the init system can load from the binary policy cache directly without doing cache validity checks. This allows for earlier policy loads.

A second phase of boot can be introduced to do validity checks and recompile policy.

Overlaying of binary policy

cache-overlay

  • ro images

Dealing with multiple policy locations and caches

Managemnt

What the parser handles

  • default values
  • --write-cache to update

What the init system needs to do

The init system is responsible for loading and managing base system policy.

  • load policy
  • replace policy
  • remove policy

Single Phase

  • the init system only ever loads or reloads binary policy

Two Phase

  • early load
  • late reload/recompile

The init system does an early load of binary policy using aa-load or directly calling libapparmor, and then does a later reload which checks text policy and recompiles policy if necessary via calling the apparmor_parser.

Policy can -- apparmor_parser (required for recompiles) -- aa_load -- directly calling libapparmor

What packaging is supposed to handle

  • refcounting cache dirs, shared between kernels