[apparmor] [RFC PATCH 1/1] libapparmor: Create man page for aa_stack_profile()/aa_stack_onexec()

John Johansen john.johansen at canonical.com
Wed Jan 13 06:40:18 UTC 2016


On 01/12/2016 10:10 PM, Tyler Hicks wrote:
> Thanks, John - I hadn't given a lot of thought to the policy changes
> required and this email was very helpful.
> 
> On 2016-01-12 15:10:28, John Johansen wrote:
>> On 01/11/2016 06:27 PM, Seth Arnold wrote:
>>> On Mon, Jan 11, 2016 at 05:41:43PM -0800, John Johansen wrote:

<<snip>>

>> now lets look at the stack on exec case. The stack addition is delayed
>> until exec.  The current profile will have the stack added on top, the
>> question is when and how.
>>
>> 1. stack_onexec as stack + change_onexec: stack is computed immediately
>>     but the transition is delayed until exec (this overrides any
>>     transitions and is how Tyler described it)
>>   A -- stack_onexec B -- exec --> A//&B
> 
> Yes, this is what I pictured when a program, confined by "A", calls
> aa_stack_onexec("B").
> 
>>
>> 2. stack_onexec, stack delayed until exec applied pre-exec transitions
>>   A -- stack_onexec B -- exec apply stack -- A//&B -- exec trans --> C//&D
> 
> I can't imagine much use for this flow. Unless there's a good use case,
> I think we should throw it out.
> 
>>
>> 3. stack_onexec, stack delayed until exec applied post-exec transitions
>>   A -- stack_onexec B -- exec trans -- C -- apply stack --> C//&B
> 
> I was actually thinking that this would happen when a program, confined
> by "A", calls aa_change_onexec("C//&B"). It is changing to a specific
> stack of profiles on exec instead of stacking an additional profile on
> top of its current confinement.
> 
It does. However there is a difference between an exec specified in
policy and a change directed by the application. This plays into
the exec transitions that use globbing

>> each is a viable definition and each could have their uses.
>>
>> Example 1: is like change_onexec in that it completely replaces the
>> domain transition, with a profile set computed at the time it is called.
>> Neither A nor B require a domain transition, A requires a change_profile
>> or stack_profile rule, and all intermediary permissions between
>> stack_onexec and exec need to be included in B
>>
>> This is the most like change_onexec in behavior. However a better
>> description of it is stack and apply at exec.
>>
>> Example 2: follows what happens with aa_stack, contrary to change_onexec
>>   mimics what happens with straight stacking, and like change_onexec
>>   puts all intermediary permissions between stack_onexec and exec into A.
>>   However A//&B must have exec permissions and this is contrary to how
>>   change_onexec works. That is change_onexec has a rule in A that defines
>>   the exec permission and has priority over regular domain transition
>>   rules and the target B does NOT need an exec rule.
>>
>>   We could and should have a stack_onexec or use the change_onexec rule to
>>   mitigate the first difference but that B requires and exec rule is odd,
>>   and I don't think it is a viable definition.
>>
>> Example 3: is similar to example 2 except B does not require a domain
>>   transition. It can be thought of stack on top of what ever current is
>>   after exec.
>>
>>   Rules wouldn't be required in this model but still might be desirable.
>>
>> Whether to go with 1, 3 or both depends on use cases, and how these are
>> implemented. So lets look at the exec side some more. Because exec rules
>> are also going to pickup the ability to specify stacking. Note the syntax
>> here is not final but sufficient for the discussion.
>>
>> exec rules allow naming a profile to transition to
>>   px /foo/bar -> A,
>>   px /** -> A,
>>
>> this will be extended to support specifying an explicit stack
>>   px /foo/bar -> A//&B,
>>   px /** -> A//&B,
>>
>> however we may want to be able to specify the stack based off the target
>> profile, this works for
>>   px /foo/bar -> /foo/bar//&B,
>>
>> but does not work for the rule with globbing because there can be
>> multiple targets matched.
>>   px /** -> ??//&B,
>>
>> we can get around this by either introducing a special variable
>>   px /** -> @{TARGET}//&B,
> 
> This feels like we're bending over backwards to appease the lazy policy
> author. He/She already has to define the profiles for each one of those
> targets so why not make him/her include a transition rule for each
> target?
> 
Yes and no.

Globbing, pix, and pux transitions are all used to support lazy policy.
Or another way of putting it is incremental policy. If we require that
all possible targets have profiles defined and that all profiles exist
in a set at author ship and at compile time, we can drop domain globbing,
pix, and pux transitions. As well as being able to specify the target.

The compile time requirement:
  means no incremental policy load, policy must be compiled and loaded
  as a set. Replacing a single profile means that all profiles must be
  updated. At the very least if any single profile as a relation that
  changes everyone that could be involved must be loaded in the set.

  I am not against doing this. It has several advantages in that static
  compile time checks can be done and many optimizations. However this
  is not possible at this time. It will be a lot of work, and currently
  too many things rely on incremental replacement.

The time of author ship requirement:
  All these possible relations must be resolved before policy will
  compile. If any profile is added that setups a new relation other
  profiles need to be updated as well.

  There are ways to deal with this via includes etc, but globbing,
  pix, and pux rules also are a means of solving this, even under
  the compile time requirement, as the compile can expand and
  resolve these.

  I can assure you that we will need ways to ease update of profile
  relations whether we stay with the current incremental compile and
  load or whether move to a single atomic compile and load.

>> or extending the stacking syntax a little to mean use the target and
>> what is specified.
>>   px /** -> &B,   # leading & specifies use target and stack B
>>
>> however neither of these syntaxes are sufficient (for globbing rules) to
>> specify the final confinement when we want the execed process to have
>> current confinement and B. We can extend each syntax to support this.
>>
>>   px /** -> @{SELF}//&B,
>>   #Note: @{PROFILE} is not correct as the task may already have
>>   #      a stack of profiles, so it is current confinement
>>
>> and
>>   ix /** -> &B,			# notice ix instead of px
>>
>>
>> notice how the choices 1 and 3 for stack_onexc parallel the above exec
>> rules.
>>   1. is the same as
>>       px /** -> @{SELF}//&B,
>>     or
>>       ix /** -> &B,
>>
>>   3. is the same as
>>      px /** -> @{TARGET}//&B,
>>    or
>>      px /** -> &B,
>>
>> both cases have their uses, and I believe we need to support both. So
>> the stack api should probably support both as well.
> 
> I already mentioned this above but I think the stack API does, as
> proposed, if aa_change_onexec() can be made to accept a string
> representing a profile stack.
> 

It can and will

>>
>> Now to the matter of whether stacking rule in the profile is required.
>>
>> 1. requires a rules otherwise it can be exploited, as Seth has
>>    already pointed out.
>>
>> 3. doesn't require a rule but it probably should use them, mostly
>>    so for consistency with 1.
>>
>> The question still remains whether we use change_profile rules or
>> introduce a separate stacking rule.
>>
>> If we go with change_profile rules then
>>   change_profile -> A,
>>   change_profile -> B,
>>
>> grants enough permissions for stacking to A//&B, however it grants wider
>> permissions than necessary as it also allows a transition to just B,
>> which may not be desired. Which means at the least we need to augment
>> change_profile to support the more restrictive case.
>>   change_profile -> A//&B,
>>
>> we could do the same with a special stack rule
>>   stack -> A//&B,
>>   stack -> @{SELF}//&B,
>>
>> but I see no reason to limit the change_profile api to not allow
>> specifying compound targets. ie. I can see using change_profile to
>>   change_profile  C//&D,
> 
> Agreed.
> 
> The existing change_profile rule could be used for specifying specific
> compound targets while a new stack_profile rule could be introduced for
> stacking a single or compound target with the current confinement.
> 
well assuming the @{target} is fixed and known. Again its an incremental
policy issue.

>> this is an immediate change to this confinement and there is no exec
>> target involved. Further once delegation lands we will want to be able
>> to specify targets with delegation.
>>   change_profile  A//+E,
>>
>> at which point I think change_profile, stacking and delegation rules are
>> more complex than combining into a single rule as each of them are going
>> to have to support bits of the other.
>>
>> yes this does mean the stacking api is really just a convenience layer
>> on top of change_profile, but that isn't a bad thing.
> 
> There's certainly a lot of overlap but if we are consistent in policy,
> API, and documentation about the differences between "change" and
> "stack" then I think everyone will benefit. At the minimum, everyone
> will suffer a little less... :)
> 
Yep, I think providing simplified interfaces are a huge benefit.




More information about the AppArmor mailing list