[apparmor] RFC: Policy versioning

Jamie Strandboge jamie at canonical.com
Mon Dec 11 17:30:21 UTC 2017


On Sun, 2017-12-10 at 03:05 -0800, John Johansen wrote:
> Currently we have a few problems with policy that must be addressed
> 

Thanks for this writeup! I'm still processing a lot of it, but there
were a couple of things I wanted to comment on right away...

> 
> I. Proposed Solution

...

> 2. Support multiple policy caches
> 
>   To address problems 3-4 we extend the poliy cache so that we retain
>   a compiled policy per kernel installed. When a new kernel is
>   installed we build a new policy cache for it.

Big +1 on supporting multiple policy caches. It does seem like we would
want to still compile (versioned!) policy on boot if the policy cache
does not yet exist to gracefully handle situations where the kernel
packaging didn't yet do it, no? This would avoid a flag day for
everyone to adjust their kernel install packaging scripts at the same
time.

I'd have to think through the implications for snappy here since the
kernel is shipped as a snap since nothing is (currently) executed upon
install. It is possible to run install hooks/etc on this, so the
proposal is not on its face problematic.
 
> 3. Standardize policy config dir and files
> 
>   Problem 5 is addressed by standardizing a config directory and file
>   layout. New locations must be added to the config dir to inform
>   apparmor of new policy locations and how they should be handled.
> 
>   The parser config has proven insufficient so Ubuntu has been
>   modifying the initscript to manage this which is not a solution
> that
>   can be shared across distros, nor does it provide a solution that
>   works with other parts of apparmor like the tools.
> 
>   Instead we have a directory in which each new location can drop its
>   own config, allowing to set its policy and include location cache,
>   and even compiler options if so desired.
> 
This makes a lot of sense. Are you envisioning apparmor would handle
all policy loads? For example, today snapd modifies policy in it own
area in /var/lib/snapd, outputs cache in /var/cache/apparmor and uses
its own options. Setting the cache and options is clear from a snapd-
perspective, what does setting the policy location imply? Or put
another way, how does this interact with '5', below?

> 
> 4. Limit distros ability to compile policy to the current kernels
>    feature abi
> 
>   Along with this Distros will no longer be able to set a default
>   policy compile that will use the current kernel's abi. This will
> not
>   even be supported at the distro level as the project can not afford
>   to break the feature abi of current policy for kernel developers.
> 
>   To address this a new tool will be added to extract the kernel
>   features abi, and tooling will be updated to allow users update a
>   profiles abi and thus begin development on newer versions.
> Basically
>   a per user opt in only approach.

I'm a little confused by this. Why would it be bad for a distro to
compile policy to a *versioned* policy cache for the current feature
abi? I understand wanting to obsolete *un*versioned policy caches.

> 
> 5. Applications managing policy and unknown profiles
> 
>   The current solution to problem 6 of having unknown policy and
>   relying on aa-remove-unknown is more problematic. We are going to
>   have to break existing behavior to fix it.
> 
>   Applications that want to manage their own policy are going to have
>   to register to do so. This will require a new API for applications
>   to use which could just be a thin layer on top of the policy config
>   file.

This sounds fine and is not onerous. The few applications that manage
their own profiles (eg, libvirt, lxd, snapd, etc) are typically
following the cutting edge of apparmor development and are already
making changes to policy for new rules, so a small change to register
going forward seems ok to me.

...

> 6.1 New variables
> 
>   The @{abi} or @{version} variable that will be defined as part of
>   the abi include can be used by the rest of the includes to
>   selectively include rules that are abi specific
> 
>   eg. the <abstractions/base> abstraction can do an include on
> 
>    <abstractions/@{abi}/base>
> 
> 
>   In addition to the @{abi} variable the parser should make the full
>   feature set available for finer grained decision making.
> 
>   if @{features/network/af_unix} {
>      ...
>   }

I like this type of rule.

> 6.2 Conditional include
> 
...

>   The syntax needs to be decided on, but some suggestions that have
>   been thrown around in the past are:
> 
> 
>   * Make style
> 
>     with a - at the start of the line, in apparmor's case it would be
>     a special qualifier that for the time being only applies to
>     includes.
> 
>     - include <abstractions/@{abi}>

This reads like it is (part of) a comment. I don't particularly care
for it. Not sure which of the others I prefer so won't comment further.

...

> 7. Dealing with new policy features on older releases.
> 
>   Where possible the parser supports downgrading rules. However this
>   only works for rule types that the parser knows about. To support
>   newer policy features on older releases the best solution is
>   dropping the newest version of apparmor into an older release.
>   However this is not always possible.
> 
> 
> 7.1 Wrapping rules in conditionals
> 
>   With the feature set being exported as conditionals it becomes
>   possible for policy to wrap new feature rules in conditionals.
> 
>   eg.
> 
>     if @{features/network/af_unix} {
>        unix peer=foo,
>     }
> 
>   While this addresses the need to do special casing in policy
>   packaging, it makes policy harder to read.

Actually, I don't find this particularly hard to read and like the
syntax quite a bit.

> 
> 7.2 Supporting unknown rule templates
> 
>   Instead of wrapping new rule types in conditionals we should extend
>   policy to support rule templates. Rule templates would allow
> userspace
>   to specify patterns for unknown rule types, so that the parser or
>   tools can parse the rule, and ignore it.
> 
>   The Rule templates could then be dropped into the abstractions,
>   as new features are added providing an easy way to update older
>   userspaces to ignore new rule types.
> 
>   eg.
>     if !supports(key) {
>       template key='key\w.*,'		# yes its overly simple
>     }
> 
>   Such rule templates wouldn't completely remove the need for being
>   able to wrap some policy in conditionals, but it done properly it
>   should be able to support most cases.
> 
IMO this would make auditing policy a bit harder since you have to
either do a preprocess run for auditing (not necessarily a bad thing). 

Mostly though as a policy author I like to group rules together in
arbitrary ways. For example, if I have an 'ix' rule, I might put the
file access rules next to it, with the unix rule next. Eg:

  #
  # foo rules
  #
  /usr/bin/foo ix,
  # needed by foo for ...
  /etc/blah r,
  # foo connects to this for ...
  unix ...,

  #
  # bar rules
  #
  /usr/bin/bar ix,
  # bar connects to this for ...
  unix ...,

IIUC, the rule templates put the unix rules somewhere else, outside of
the context of the need for the rule.

--
Jamie Strandboge             | http://www.canonical.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: This is a digitally signed message part
URL: <https://lists.ubuntu.com/archives/apparmor/attachments/20171211/a474a5b8/attachment.sig>


More information about the AppArmor mailing list