AppArmorPolicyView

From AppArmor
Jump to: navigation, search

Related Documents

AppArmor Policy Table of Contents

AppArmor Policy Namespaces Table of Contents

Introduction

The policy view determines whether a namespace is treated as the root for policy visibility. By default when a new policy namespace is created it is also treated as a new policy view. This feature is used by containers like LXD to load and treat their policy as if it is the root system policy. Note that there are cases where the use of policy namespaces is beneficial but a new view is not desired. Eg, setting up user roles or application sandboxing where visibility of system policy is desirable.

The policy view affects how policy is authored because it affects the names that are used in transitions and for communication between tasks. As such policy must be authored with a certain view in mind. It is the policy author's responsibility to ensure the policy and views required for a namespace are correctly setup.

TODO: transitions between profiles in different namespaces...

Namespace View

AppArmor policy namespaces are strictly hierarchical but the full hierarchy may not be visible to all tasks. A virtualized view of the policy namespace hierarchy may be set and tasks under that view can as a result only see the portion of the hierarchy within their view.

 Eg. Given a hierarchy of :ns1//ns2:  and a view set to :ns1: then only the profiles in ns1 and ns2 will be visible.

The profile introspection and management interfaces are virtualized to the current namespace view of the task doing profile management or introspection. Note: See Interfaces and current view???(or is it current namespace???) for additional notes

The View acts as the root namespace for tasks assigned to that view, and the name of the View namespace will not be reported to tasks in that view.

 Eg. If profile foo is loaded into :ns1:, and Task A has its View set to :ns1: then when task one introspects
     task B confined by :ns1:foo it will see the confinement of task B as just foo. Tasks outside the
     view may be able to see the full hierarchy or nothing depending on their own views.

While the AppArmor interfaces are virtualized, depending on how the kernel and other system namespaces (proc, user, ...) are configured it may be possible to introspect a task that is outside of the namespace View. In this situation the confinement of the task will be reported as having the name ---. AppArmor will not expose the namespace name nor the profile name of the task.

 Eg. Given the namespaces
   root policy namespace
   :ns1:
   :ns1//ns2:
   :ns3:
 And the following tasks and views
   Task A has a view set to the root system policy namespace, with it confinement set to unconfined
   Task B has a view set to ns1, with its confinement set to unconfined of namespace :ns1:
   Task C has a view set to ns1//ns2, with its confinement set to unconfined of namespace :ns1//ns2:
   Task D has a view set to ns3, with its confinement set to unconfined of namespace :ns3:
 Then
   Task A
   - can see profiles in the system namespace
   - can see the namespaces :ns1:, :ns1//ns2:, and :ns3: and the profiles in them
   - sees the confinement of
     Task A (itself) as unconfined
     Task B as :ns1:unconfined
     Task C as :ns1//ns2:unconfined
     Task D as :ns3:unconfined
   Task B
   - can NOT see profiles in the system namespace
   - can see profiles in namespaces :ns1: which appears to be the root system namespace to it
   - sees namespace :ns1//ns2: as :ns2: and can see the profiles in it
   - can NOT see namespace :ns3: nor the profiles in it
   - sees the confinement of
     Task A as --- 
     Task B (itself) as unconfined
     Task C as :ns2:unconfined
     Task D as ---
   Task C
   - can NOT see profiles in the system namespace
   - can NOT see namespace :ns1: nor :ns3: nor their profiles
   - can see profiles in namespaces :ns1//ns2: which appears to be the root system namespace to it
   - sees the confinement of
     Task A as ---
     Task B as ---
     Task C (itself) as unconfined
     Task D as ---
   Task D
   - can NOT see profiles in the system namespace
   - can NOT see namespace :ns1: nor :ns1//ns2: nor their profiles
   - can see profiles in namespaces :ns3: which appears to be the root system namespace to it
   - sees the confinement of
     Task A as ---
     Task B as ---
     Task C as ---
     Task D (itself) as unconfined

How the Namespace View affects Policy

The namespace view not only affects what policy is visible from a task but also affects how policy needs to be authored, and managed.

TODO

Namespace View and policy transitions

Namespace View and policy management

??? how is the view of a namespace set

  • Note: Before AppArmor 4, the View and current namespace are the same

Defining/Setting the Namespace View

There are two ways that a namespace view can be set. It can be defined in policy, or if policy does not explicitly define the namespace view it can be set via the apparmorfs interface (used by the api).

Defining the View in Policy

The view is set relative to the namespace the policy is being defined for.

 namespace ns1 {
     view ./, # view of ns1 is set to the policy root 
namespace ns2 { view ns1, # view of ns1//ns2 is set to that of ns1
profile D { ... } }
namespace ns3 { # view not defined so set to ns1//ns3 profile E { ... } }
profile C { ... } }
profile A { ... }
profile :ns1:B { # profile defined external to its namespace block, view is still set in namespace block ... }

Setting the View via the apparmorfs interface

The apparmorfs interface can be used to set a namespace view when policy does not define the view of the namespace. This is usually occurs because the namespace is being dynamically created by a trusted helper (lxd, pam, ..), and the policy of the new namespace doesn't have to directly interact with existing policy. When a namespace is created without its view being set, either via the profile load interface, or the apparmorfs interface, the namespace's view is defaulted to its self (its policy will not see existing policy on the system).

The View of a policy namespace can be set by a task in an ancestor namespace with admin rights over the namespace. The setting task can set the namespace view to any namespace it can view including its own view. A task confined by the namespace can not change the view of the namespace, in fact once a task is confined by the namespace its view can not be changed.

The View of a namespace can be set by writing to the view file under the its namespace directory. Eg. to set the View of namespace ns1 to the current tasks view it could write

 echo "." > /sys/kernel/security/apparmor/policy/namespaces/ns1/view

Current Namespace(s)

When a task is created it is assigned to a policy namespace (usually inherited from its parent). When stacking is used the task may be assigned to multiple policy namespaces. From a mediation point of view all of the task's namespaces are active and enforced (even the ones out of the task's view). Once a task has entered a namespace there is no way for it to leave that policy namespace unless so directed/defined in the policy of that namespace. The current namespace of a given task is the namespace of the task's label or if the label is composed of multiple profiles it is namespace that is the furtherest descendent from the system's root namespace.

That is if the task is confined by

 profile_A//:ns1:profile_B//:ns1//ns2:profile_C

the current namespace will be ns1//ns2.

The current task's namespace is not directly used in mediation but is used to find a task's

  • current View namespace
  • current Scope namespace

which are used in mediation.

The current namespace is always the Scope namespace or one of its children, it can never be a parent of the namespace Scope, and the Scope namespace is always the same as the View namespace or one of its children. (ie. current View >= current Scope >= current namespace)

  • Note: Before Version 4.0 of the AppArmor kernel module the current namespace was always set as the current View such that the current namespace always appeared to be the root namespace for tasks in that namespace.

Current View

The current View namespace of a task governs which namespace is used for profile lookups, profile attachments, and transitions. It also determines what part of the confinement stack can be viewed by a task when doing introspection. The current View is determined by the view namespace of the the task's current namespace. The current view will be the same as the current namespace or an ancestor of it.

Eg. given a child namespace :child1: with its view set to the root namespace and with profile R in the root namespace, profile C in the the child namespace, task Tr confined by R and task Tc confined by C, then
 Tr - views Tc confinement as :child1:C
    - views its own confinement as R
 Tc - views its own confinement as :child1:C
    - views Tr confinement as R

Now lets say Tc and Tr both try to transition to a profile X

 Tr will transition to X in the root namespace
 Tc will transition to a different profile X in the namespace :child1: because its current namespace is :child1: and profile lookups that don't specify a namespace are relative to the current namespace.

However if the transitions is to :child1:X

 Tr will transition to the X profile in :child1:
 Tc will still transition to the X profile in :child1:

This is because the namespace lookup is relative to the view not the current profile.

Similarly if the transitions is to :child2:Y

 Tr will transition to the Y profile in :child2:
 Tc will transition to the Y profile in :child2:


??? Eg. A transition of

 px /** -> /bin/foo,

is relative to the current namespace.

While a transition of

 px /** -> :foo:/bin/foo,

is relative to the current view.