| <html devsite> |
| <head> |
| <title>Policy Compatibility</title> |
| <meta name="project_path" value="/_project.yaml" /> |
| <meta name="book_path" value="/_book.yaml" /> |
| </head> |
| <body> |
| <!-- |
| Copyright 2018 The Android Open Source Project |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| //www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| |
| <p> |
| This article describes how Android handles the policy compatibility issues |
| with platform OTAs, where new platform SELinux settings may differ from old vendor |
| SELinux settings. |
| </p> |
| <p> |
| Treble-based SELinux policy design considers a binary distinction |
| between <em>platform</em> and <em>vendor</em> policy; the scheme becomes |
| more complicated if vendor partitions generate dependencies, such as |
| <code>platform</code> < <code>vendor</code> < <code>oem</code>. |
| </p> |
| <p> |
| In Android 8.0 and higher, SELinux global policy is divided into private and |
| public components. Public components consist of the policy and associated |
| infrastructure, which are guaranteed to be available for a platform version. |
| This policy will be exposed to vendor policy writers to enable vendors to build |
| a vendor policy file, which when combined with the platform-provided policy, |
| results in a fully-functional policy for a device. |
| </p> |
| |
| <ul> |
| <li>For versioning, the exported platform-public policy will be written as |
| <em>attributes</em>.</li> |
| <li>For ease of policy writing, exported types will be transformed into |
| <em>versioned attributes</em> as part of the policy build process. Public |
| types may also be used directly in labeling decisions provided by vendor |
| contexts files.</li> |
| </ul> |
| <p> |
| <strong>Android maintains a mapping between exported concrete types in platform |
| policy and the corresponding versioned attributes for each platform |
| version</strong>. This ensures that when objects are labeled with a type, it |
| does not break behavior guaranteed by the platform-public policy in a previous |
| version. This mapping is maintained by keeping a mapping file up-to-date for |
| <a href="https://android.googlesource.com/platform/system/sepolicy/+/master/prebuilts/api" class="external"> |
| each platform version</a>, which keeps attribute membership information for each |
| type exported in public policy. |
| </p> |
| |
| <h2 id="object-ownership-and-labeling">Object ownership and labeling</h2> |
| <p> |
| When customizing policy in Android 8.0 and higher, ownership must be clearly defined |
| for each object to keep platform and vendor policy separate. For example, if |
| the vendor labels <code>/dev/foo</code> and the platform then labels |
| <code>/dev/foo</code> in a subsequent OTA, there will be undefined behavior. For |
| SELinux, this manifests as a labeling collision. The device node can have only a |
| single label which resolves to whichever label is applied last. As a result: |
| </p> |
| <ul> |
| <li>Processes that <em>need access</em> to the unsuccessfully applied label will |
| lose access to the resource.</li> |
| <li>Processes that <em>gain access</em> to the file may break because the wrong |
| device node was created.</li> |
| </ul> |
| <p> |
| System properties also have potential for naming collisions that could result in |
| undefined behavior on the system (as well as for SELinux labeling). Collisions |
| between platform and vendor labels can occur for any object that has an SELinux |
| label, including properties, services, processes, files, and sockets. To avoid |
| these issues, clearly define ownership of these objects. |
| </p> |
| <p> |
| In addition to label collisions, SELinux type/attribute names may also collide. |
| A type/attribute name collision will always result in a policy compiler error. |
| </p> |
| <h3 id="type-attribute-namespacing">Type/attribute namespacing</h3> |
| <p> |
| SELinux does not allow multiple declarations of the same type/attribute. Policy |
| with duplicate declarations will fail to compilation. To avoid type and |
| attribute name collisions, all vendor declarations should be namespaced |
| starting with <code>np_</code>. |
| </p> |
| |
| |
| <pre |
| class="prettyprint">type foo, domain; → type np_foo, domain;</pre> |
| |
| <h3 id="system-property-and-process-labeling-ownership">System property and |
| process labeling ownership</h3> |
| <p> |
| Avoiding labeling collisions is best solved using property namespaces. To |
| easily identify platform properties and avoid name conflicts when renaming or |
| adding exported-platform properties, ensure all vendor properties have their |
| own prefixes: |
| </p> |
| <table> |
| <tr> |
| <th>Property type</th> |
| <th>Acceptable prefixes</th> |
| </tr> |
| <tr> |
| <td>read-writable</td> |
| <td><code>vendor.</code></td> |
| </tr> |
| <tr> |
| <td>read-only</td> |
| <td><code>ro.vendor.</code><br> |
| <code>ro.boot.</code><br> |
| <code>ro.hardware.</code> |
| </td> |
| </tr> |
| <tr> |
| <td>persistent</td> |
| <td><code>persist.vendor.</code></td> |
| </tr> |
| </table> |
| <p> |
| Vendors can continue to use <code>ro.boot.*</code> (which comes from the kernel |
| cmdline) and <code>ro.hardware.*</code> (an obvious hardware-related property). |
| </p> |
| <p> |
| All the vendor services in init rc files should have <code>vendor.</code> |
| for services in init rc files of non-system partitions. Similar rules are |
| applied to the SELinux labels for the vendor properties (<code>vendor_</code> |
| for the vendor properties). |
| </p> |
| <h3 id="file-ownership">File ownership</h3> |
| <p> |
| Preventing collisions for files is challenging because platform and vendor |
| policy both commonly provide labels for all filesystems. Unlike type naming, |
| namespacing of files is not practical since many of them are created by the |
| kernel. To prevent these collisions, follow the naming guidance for filesystems |
| in this section. For Android 8.0, these are recommendations without technical |
| enforcement. In the future, these recommendations will be enforced by the |
| <a href="/compatibility/vts/">Vendor Test Suite</a> (VTS). |
| </p> |
| <h4 id="system">System (/system)</h4> |
| <p> |
| Only the system image must provide labels for <code>/system</code> components |
| through <code>file_contexts</code>, <code>service_contexts</code>, etc. If labels |
| for <code>/system</code> components are added in <code>/vendor</code> policy, a |
| framework-only OTA update may not be possible. |
| </p> |
| <h4 id="vendor">Vendor (/vendor)</h4> |
| <p> |
| The AOSP SELinux policy already labels parts of <code>vendor</code> partition |
| the platform interacts with, which enables writing SELinux rules for platform |
| processes to be able to talk and/or access parts of <code>vendor</code> |
| partition. Examples: |
| </p> |
| <table> |
| <tr> |
| <th><code>/vendor</code> path</th> |
| <th>Platform-provided label</th> |
| <th>Platform processes depending on the label</th> |
| </tr> |
| <tr> |
| <td><code>/vendor(/.<strong>*</strong>)?</code> |
| </td> |
| <td><code>vendor_file</code> |
| </td> |
| <td>All HAL clients in framework, <code>ueventd</code>, etc. |
| </td> |
| </tr> |
| <tr> |
| <td><code>/vendor/framework(/.<strong>*</strong>)?</code> |
| </td> |
| <td><code>vendor_framework_file</code> |
| </td> |
| <td><code>dex2oat</code>, <code>appdomain</code>, etc. |
| </td> |
| </tr> |
| <tr> |
| <td><code>/vendor/app(/.<strong>*</strong>)?</code> |
| </td> |
| <td><code>vendor_app_file</code> |
| </td> |
| <td><code>dex2oat</code>, <code>installd</code>, <code>idmap</code>, etc. |
| </td> |
| </tr> |
| <tr> |
| <td><code>/vendor/overlay(/.<strong>*</strong>)</code> |
| </td> |
| <td><code>vendor_overlay_file</code> |
| </td> |
| <td><code>system_server</code>, <code>zygote</code>, <code>idmap</code>, etc. |
| </td> |
| </tr> |
| </table> |
| <aside class="note"> |
| <strong>*</strong> For more examples, see |
| <a href="https://android.googlesource.com/platform/system/sepolicy/+/master/private/file_contexts" class="external"> |
| <code>system/sepolicy/private/file_contexts</code></a>.</aside> |
| |
| <p> |
| As a result, specific rules must be followed (enforced through |
| <code>neverallows</code>) when labelling additional files in <code>vendor</code> |
| partition: |
| </p> |
| <ul> |
| <li><code>vendor_file </code>must be the default label for all files in |
| <code>vendor</code> partition. The platform policy requires this to access |
| passthrough HAL implementations.</li> |
| <li>All new <code>exec_types</code> added in <code>vendor</code> partition |
| through vendor SEPolicy must have <code>vendor_file_type</code> attribute. This |
| is enforced through neverallows.</li> |
| <li>To avoid conflicts with future platform/framework updates, avoid labelling |
| files other than <code>exec_types</code> in <code>vendor</code> partition.</li> |
| <li>All library dependencies for AOSP-identified same process HALs must be |
| labelled as <code>same_process_hal_file.</code></li></ul> |
| |
| <h4 id="procfs">Procfs (/proc)</h4> |
| <p> |
| Files in <code>/proc</code> may be labeled using only the <code>genfscon</code> |
| label. In Android 7.0, both the |
| <a href="https://android.googlesource.com/platform/system/sepolicy/+/nougat-dr1-release/genfs_contexts" class="external">platform</a> |
| and <a |
| href="https://android.googlesource.com/device/google/marlin/+/nougat-dr1-release/sepolicy/genfs_contexts" class="external">vendor</a> |
| policy used <code>genfscon</code> to label files in <code>procfs</code>. |
| </p> |
| <p> |
| <strong>Recommendation:</strong> Only platform policy labels <code>/proc</code>. |
| If <code>vendor</code> processes need access to files in <code>/proc</code> that |
| are currently labeled with the default label (<code>proc</code>), vendor policy |
| should not explicitly label them and should instead use the generic |
| <code>proc</code> type to add rules for vendor domains. This allows the platform |
| updates to accommodate future kernel interfaces exposed through |
| <code>procfs</code> and label them explicitly as needed. |
| </p> |
| <h4 id="debugfs">Debugfs (/sys/kernel/debug)</h4> |
| <p> |
| <code>Debugfs</code> can be labeled in both <code>file_contexts</code> and |
| <code>genfscon</code>. In Android 7.0, both platform and vendor label |
| <code>debugfs</code>. |
| </p> |
| <p> |
| <strong>Recommendation:</strong> In the short term, only vendor policy may label |
| <code>debugfs</code>. In the long term, remove <code>debugfs</code>. |
| </p> |
| <h4 id="tracefs">Tracefs |
| (/sys/kernel/debug/tracing)</h4> |
| <p> |
| <code>Tracefs</code> can be labeled in both <code>file_contexts</code> and |
| <code>genfscon</code>. In Android 7.0, only the platform labels |
| <code>tracefs</code>. |
| </p> |
| <p> |
| <strong>Recommendation:</strong> Only platform may label <code>tracefs</code>. |
| </p> |
| <h4 id="sysfs">Sysfs (/sys)</h4> |
| <p> |
| Files in <code>/sys</code> may be labeled using both <code>file_contexts</code> |
| and <code>genfscon</code>. In Android 7.0, both platform and vendor use |
| <code>file_contexts</code> and <code>genfscon</code> to label files in |
| <code>sysfs</code>. |
| </p> |
| <p> |
| <strong>Recommendation:</strong> The platform may label <code>sysfs</code> |
| nodes that are not device-specific. Otherwise, only vendor may label files. |
| </p> |
| <h4 id="tmpfs">tmpfs (/dev)</h4> |
| <p> |
| Files in <code>/dev</code> may be labeled in <code>file_contexts</code>. In |
| Android 7.0, both platform and vendor label files here. |
| </p> |
| <p> |
| <strong>Recommendation:</strong> Vendor may label only files in |
| <code>/dev/vendor</code> (e.g., <code>/dev/vendor/foo</code>, |
| <code>/dev/vendor/socket/bar</code>). |
| </p> |
| <h4 id="rootfs">Rootfs (/)</h4> |
| <p> |
| Files in <code>/</code> may be labeled in <code>file_contexts</code>. In Android |
| 7.0, both platform and vendor label files here. |
| </p> |
| <p> |
| <strong>Recommendation:</strong> Only system may label files in <code>/</code>. |
| </p> |
| <h4 id="data-data">Data (/data)</h4> |
| <p> |
| Data is labeled through a combination of <code>file_contexts</code> and |
| <code>seapp_contexts</code>. |
| </p> |
| <p> |
| <strong>Recommendation:</strong> Disallow vendor labeling outside |
| <code>/data/vendor</code>. Only platform may label other parts of |
| <code>/data</code>. |
| </p> |
| |
| <h2 id="compatibility-attributes">Compatibility attributes</h2> |
| <p> |
| SELinux policy is an interaction between source and target types for specific |
| object classes and permissions. Every object (processes, files, etc.) affected |
| by SELinux policy may have only one type, but that type may have multiple |
| attributes. |
| </p> |
| <p> |
| Policy is written mostly in terms of existing types: |
| </p> |
| |
| |
| <pre |
| class="prettyprint">allow source_type target_type:target_class permission(s);</pre> |
| <p> |
| This works because the policy was written with knowledge of all types. However, |
| if the vendor policy and platform policy use specific types, and the label of a |
| specific object changes in only one of those policies, the other may contain |
| policy that gained or lost access previously relied upon. For example: |
| </p> |
| |
| |
| <pre class="prettyprint">File_contexts: |
| /sys/A u:object_r:sysfs:s0 |
| Platform: allow p_domain sysfs:class perm; |
| Vendor: allow v_domain sysfs:class perm;</pre> |
| <p> |
| Could be changed to: |
| </p> |
| |
| |
| <pre class="prettyprint">File_contexts: |
| /sys/A u:object_r:sysfs_A:s0</pre> |
| <p> |
| Although the vendor policy would remain the same, the <code>v_domain</code> |
| would lose access due to the lack of policy for the new <code>sysfs_A</code> |
| type. |
| </p> |
| <p> |
| By defining a policy in terms of attributes, we can give the underlying object a |
| type that has an attribute corresponding to policy for both the platform and |
| vendor code. This can be done for all types to effectively create an |
| <em>attribute-policy</em> wherein concrete types are never used. In practice, |
| this is required only for the portions of policy that overlap between platform |
| and vendor, which are defined and provided as <em>platform public policy</em> |
| that gets built as part of the vendor policy. |
| </p> |
| <p> |
| Defining public policy as versioned attributes satisfies two policy |
| compatibility goals: |
| </p> |
| <ul> |
| <li><strong>Ensure vendor code continues to work after platform update</strong>. |
| Achieved by adding attributes to concrete types for objects corresponding to |
| those on which vendor code relied, preserving access.</li> |
| <li><strong>Ability to deprecate policy</strong>. Achieved by clearly |
| delineating policy sets into attributes that can be removed as soon as the |
| version to which they correspond no longer is supported. Development can |
| continue in the platform, knowing the old policy is still present in the |
| vendor policy and will be automatically removed when/if it upgrades.</li> |
| </ul> |
| |
| <h3 id="policy-writability">Policy writability</h3> |
| <p> |
| To meet the goal of not requiring knowledge of specific version changes for |
| policy development, Android 8.0 includes a mapping between platform-public |
| policy types and their attributes. Type <code>foo</code> is mapped |
| to attribute <code>foo_v<em>N</em></code>, where <code><em>N</em></code> is the |
| version targeted. <code>vN</code> corresponds to the |
| <code>PLATFORM_SEPOLICY_VERSION</code> build variable and is of the form |
| <code>MM.NN</code>, where <code>MM</code> corresponds to the platform SDK number |
| and <code>NN</code> is a platform sepolicy specific version. |
| </p> |
| <p> |
| Attributes in public policy are not versioned, but rather exist as an API on |
| which platform and vendor policy can build to keep the interface between the two |
| partitions stable. Both platform and vendor policy writers can continue to write |
| policy as it is written today. |
| </p> |
| <p> |
| Platform-public policy exported as <code>allow source_foo target_bar:<em>class |
| perm</em>;</code>is included as part of the vendor policy. During |
| <a href="/security/selinux/build">compilation</a> (which includes the |
| corresponding version) it is transformed into the policy that will go to the |
| vendor portion of the device (shown in the transformed Common Intermediate |
| Language (CIL)): |
| </p> |
| <pre |
| class="prettyprint"> (allow source_foo_vN target_bar_vN (class (perm)))</pre> |
| <p> |
| As vendor policy is never ahead of the platform, it should not be concerned with |
| prior versions. However, platform policy will need to know how far back vendor |
| policy is, include attributes to its types, and set policy corresponding to |
| versioned attributes. |
| </p> |
| |
| <h3 id="policy-diffs">Policy diffs</h3> |
| <p> |
| Automatically creating attributes by adding <code>_v<em>N</em></code> to the end |
| of each type does nothing without mapping of attributes to types across version |
| diffs. Android maintains a mapping between versions for attributes and a |
| mapping of types to those attributes. This is done in the aforementioned mapping |
| files with statements, such as (CIL): |
| </p> |
| |
| <pre class="prettyprint">(typeattributeset foo_vN (foo))</pre> |
| |
| <h4 id="platform-upgrades">Platform upgrades</h4> |
| <p> |
| The following section details scenarios for platform upgrades. |
| </p> |
| |
| <h5 id="same-types">Same types</h5> |
| <p> |
| This scenario occurs when an object does not change labels in policy versions. |
| This is the same for source and target types and can be seen with |
| <code>/dev/binder</code>, which is labeled <code>binder_device</code> across all |
| releases. It is represented in transformed policy as: |
| </p> |
| |
| |
| <pre class="prettyprint">binder_device_v1 … binder_device_vN</pre> |
| <p> |
| When upgrading from <code>v1</code> → <code>v2</code>, the platform policy must |
| contain: |
| </p> |
| |
| |
| <pre |
| class="prettyprint">type binder_device; -> (type binder_device) (in CIL)</pre> |
| <p> |
| In the v1 mapping file (CIL): |
| </p> |
| |
| |
| <pre |
| class="prettyprint">(typeattributeset binder_device_v1 (binder_device))</pre> |
| <p> |
| In the v2 mapping file (CIL): |
| </p> |
| |
| |
| <pre |
| class="prettyprint">(typeattributeset binder_device_v2 (binder_device))</pre> |
| <p> |
| In the v1 vendor policy (CIL): |
| </p> |
| |
| |
| <pre class="prettyprint">(typeattribute binder_device_v1) |
| (allow binder_device_v1 …)</pre> |
| <p> |
| In the v2 vendor policy (CIL): |
| </p> |
| |
| |
| <pre class="prettyprint">(typeattribute binder_device_v2) |
| (allow binder_device_v2 …)</pre> |
| <h5 id="new-types">New types</h5> |
| <p> |
| This scenario occurs when the platform has added a new type, which can happen |
| when adding new features or during policy hardening. |
| </p> |
| <ul> |
| <li><strong>New feature</strong>. When the type is labeling an object that was |
| previously non-existent (such as a new service process), the vendor code did not |
| previously interact with it directly so no corresponding policy exists. The new |
| attribute corresponding to the type does not have an attribute in the previous |
| version, and so would not need an entry in the mapping file targeting that |
| version.</li> |
| <li><strong>Policy hardening</strong>. When the type represents policy |
| hardening, the new type attribute must link back to a chain of attributes |
| corresponding to the previous one (similar to the previous example changing |
| <code>/sys/A</code> from <code>sysfs</code> to <code>sysfs_A</code>). Vendor |
| code relies on a rule enabling access to <code>sysfs</code>, and needs |
| to include that rule as an attribute of the new type.</li> |
| </ul> |
| |
| <p> |
| When upgrading from <code>v1</code> → <code>v2</code>, the platform policy must |
| contain: |
| </p> |
| |
| |
| <pre |
| class="prettyprint">type sysfs_A; -> (type sysfs_A) (in CIL) |
| type sysfs; (type sysfs) (in CIL)</pre> |
| <p> |
| In the v1 mapping file (CIL): |
| </p> |
| |
| |
| <pre |
| class="prettyprint">(typeattributeset sysfs_v1 (sysfs sysfs_A))</pre> |
| <p> |
| In the v2 mapping file (CIL): |
| </p> |
| |
| |
| <pre class="prettyprint">(typeattributeset sysfs_v2 (sysfs)) |
| (typeattributeset sysfs_A_v2 (sysfs_A))</pre> |
| <p> |
| In the v1 vendor policy (CIL): |
| </p> |
| |
| |
| <pre class="prettyprint">(typeattribute sysfs_v1) |
| (allow … sysfs_v1 …)</pre> |
| <p> |
| In the v2 vendor policy (CIL): |
| </p> |
| |
| |
| <pre class="prettyprint">(typeattribute sysfs_A_v2) |
| (allow … sysfs_A_v2 …) |
| (typeattribute sysfs_v2) |
| (allow … sysfs_v2 …)</pre> |
| </li></ul> |
| <h5 id="removed-types">Removed types</h5> |
| <p> |
| This (rare) scenario occurs when a type is removed, which can happen when the |
| underlying object: |
| </p> |
| <ul> |
| <li>Remains but gets a different label.</li> |
| <li>Is removed by the platform.</li> |
| </ul> |
| <p> |
| During policy loosening, a type is removed and the object labeled with that type |
| is given a different, already-existing label. This represents a merging of |
| attribute mappings: The vendor code must still be able to access the underlying |
| object by the attribute it used to possess, but the rest of the system must now |
| be able to access it with its new attribute. |
| </p> |
| <p> |
| If the attribute to which it has been switched is new, then relabeling is the |
| same as in the new type case, except that when an existing label is used, the |
| addition of the old attribute new type would cause other objects also labeled |
| with this type to be newly accessible. This is essentially what is done by the |
| platform and is deemed to be an acceptable tradeoff to maintain |
| compatibility. |
| </p> |
| |
| |
| <pre class="prettyprint">(typeattribute sysfs_v1) |
| (allow … sysfs_v1 …)</pre> |
| <p> |
| <strong>Example Version 1: Collapsing types (removing sysfs_A)</strong> |
| </p> |
| <p> |
| When upgrading from <code>v1</code> → <code>v2</code>, the platform policy must |
| contain: |
| </p> |
| |
| |
| <pre |
| class="prettyprint">type sysfs; (type sysfs) (in CIL)</pre> |
| <p> |
| In the v1 mapping file (CIL): |
| </p> |
| |
| |
| <pre class="prettyprint">(typeattributeset sysfs_v1 (sysfs)) |
| (type sysfs_A) # in case vendors used the sysfs_A label on objects |
| (typeattributeset sysfs_A_v1 (sysfs sysfs_A))</pre> |
| <p> |
| In the v2 mapping file (CIL): |
| </p> |
| |
| |
| <pre class="prettyprint">(typeattributeset sysfs_v2 (sysfs))</pre> |
| <p> |
| In the v1 vendor policy (CIL): |
| </p> |
| |
| |
| <pre class="prettyprint">(typeattribute sysfs_A_v1) |
| (allow … sysfs_A_v1 …) |
| (typeattribute sysfs_v1) |
| (allow … sysfs_v1 …)</pre> |
| <p> |
| In the v2 vendor policy (CIL): |
| </p> |
| |
| |
| <pre class="prettyprint">(typeattribute sysfs_v2) |
| (allow … sysfs_v2 …)</pre> |
| <p> |
| <strong>Example Version 2: Removing completely (foo type)</strong> |
| </p> |
| <p> |
| When upgrading from <code>v1</code> → <code>v2</code>, the platform policy must |
| contain: |
| </p> |
| |
| |
| <pre |
| class="prettyprint"># nothing - we got rid of the type</pre> |
| <p> |
| In the v1 mapping file (CIL): |
| </p> |
| |
| |
| <pre |
| class="prettyprint">(type foo) #needed in case vendors used the foo label on objects |
| (typeattributeset foo_v1 (foo))</pre> |
| <p> |
| In the v2 mapping file (CIL): |
| </p> |
| |
| |
| <pre |
| class="prettyprint"># nothing - get rid of it</pre> |
| <p> |
| In the v1 vendor policy (CIL): |
| </p> |
| |
| |
| <pre class="prettyprint">(typeattribute foo_v1) |
| (allow foo …) |
| (typeattribute sysfs_v1) |
| (allow sysfs_v1 …)</pre> |
| <p> |
| In the v2 vendor policy (CIL): |
| </p> |
| |
| |
| <pre class="prettyprint">(typeattribute sysfs_v2) |
| (allow sysfs_v2 …)</pre> |
| |
| <h5 id="new-class-permissions">New class/permissions</h5> |
| <p> |
| This scenario occurs when a platform upgrade introduces new policy components |
| that do not exist in previous versions. For example, when Android added the |
| <code>servicemanager</code> object manager that created the add, find, and list |
| permissions, vendor daemons wanting to register with the |
| <code>servicemanager</code> needed permissions that were not |
| available. In Android 8.0, only the platform policy may add new classes and |
| permissions. |
| </p> |
| <p> |
| To allow all domains that could have been created or extended by vendor policy |
| to use the new class without obstruction, the platform policy needs to include a |
| rule similar to: |
| </p> |
| |
| |
| <pre |
| class="prettyprint">allow {domain -coredomain} *:new_class perm;</pre> |
| <p> |
| This may even require policy allowing access for all interface (public policy) |
| types, to be sure vendor image gains access. If this results in unacceptable |
| security policy (as it may have with the servicemanager changes), a vendor |
| upgrade could potentially be forced. |
| </p> |
| <h5 id="removed-class-permissions">Removed class/permissions</h5> |
| <p> |
| This scenario occurs when an object manager is removed (such as the |
| <code>ZygoteConnection</code> object manager) and should not cause issues. The |
| object manager class and permissions could remain defined in policy until the |
| vendor version no longer uses it. This is done by adding the definitions |
| to the corresponding mapping file. |
| </p> |
| <h4 id="vendor-customization-for-new-relabeled-types">Vendor customization for |
| new/relabeled types</h4> |
| <p> |
| New vendor types are at the core of vendor policy development as they are needed |
| to describe new processes, binaries, devices, subsystems, and stored data. As |
| such, it is imperative to allow the creation of vendor-defined types. |
| </p> |
| <p> |
| As vendor policy is always the oldest on the device, there is no need to |
| automatically convert all vendor types to attributes in policy. The platform |
| does not rely on anything labeled in vendor policy because the platform has no |
| knowledge of it; however, the platform will provide the attributes and public |
| types it uses to interact with objects labeled with these types (such as |
| <code>domain</code>, <code>sysfs_type</code>, etc.). For the platform to |
| continue to interact correctly with these objects, the attributes and types |
| must be appropriately applied and specific rules may need to be added to the |
| customizable domains (such as <code>init</code>). |
| </p> |
| |
| <h2 id="attributes-p">Attribute changes for Android 9</h2> |
| <p> |
| Devices upgrading to Android 9 can use the following attributes, but devices |
| launching with Android 9 must not. |
| </p> |
| <h3 id="violator-attributes">Violator attributes</h3> |
| <p> |
| Android 9 includes these domain-related attributes: |
| </p> |
| <ul> |
| <li><strong><code>data_between_core_and_vendor_violators</code></strong>. |
| Attribute for all domains that violate the requirement of not sharing files by |
| path between <code>vendor</code> and <code>coredomains</code>. Platform and |
| vendor processes shouldn't use on-disk files to communicate (unstable ABI). |
| Recommendation: |
| <ul> |
| <li>Vendor code should use <code>/data/vendor</code>.</li> |
| <li>System should not use <code>/data/vendor</code>.</li> |
| </ul |
| </li> |
| <li><strong><code>system_executes_vendor_violators</code></strong>. Attribute |
| for all system domains (except <code>init</code> and <code>shell domains</code>) |
| that violate the requirement of not executing vendor binaries. Execution of |
| vendor binaries has unstable API. Platform shouldn't execute vendor binaries |
| directly. Recommendation: |
| <ul> |
| <li>Such platform dependencies on vendor binaries must be behind HIDL HALs. |
| <p> <strong><em>OR</em></strong></p></li> |
| <li><code>coredomains</code> that need access to vendor binaries should be |
| moved to the vendor partition and thus, stop being <code>coredomain</code>.</li> |
| </ul> |
| </li> |
| </ul> |
| |
| <h3 id="untrusted-attributes">Untrusted attributes</h3> |
| <p> |
| Untrusted apps that host arbitrary code shouldn't have access to HwBinder |
| services, except those considered sufficiently safe for access from such apps |
| (see safe services below). The two main reasons for this are: |
| </p> |
| <ol> |
| <li>HwBinder servers do not perform client authentication because HIDL currently |
| does not expose caller UID information. Even if HIDL did expose such data, many |
| HwBinder services either operate at a level below that of apps (such as, HALs) or |
| must not rely on app identity for authorization. Thus, to be safe, the default |
| assumption is that every HwBinder service treats all its clients as equally |
| authorized to perform operations offered by the service.</li> |
| <li>HAL servers (a subset of HwBinder services) contain code with higher |
| incidence rate of security issues than <code>system/core</code> components and |
| have access to the lower layers of the stack (all the way down to hardware) thus |
| increasing opportunities for bypassing the Android security model.</li></ol> |
| |
| <h4 id="safe-services">Safe services</h4> |
| <p> |
| Safe services include: |
| </p> |
| <ul> |
| <li><code>same_process_hwservice</code>. These services (by definition) run in |
| the process of the client and thus have the same access as the client domain in |
| which the process runs.</li> |
| <li><code>coredomain_hwservice</code>. These services do not pose risks |
| associated with reason #2.</li> |
| <li><code>hal_configstore_ISurfaceFlingerConfigs</code>. This service is |
| specifically designed for use by any domain.</li> |
| <li><code>hal_graphics_allocator_hwservice</code>. These operations are also |
| offered by <code>surfaceflinger</code> Binder service, which apps are permitted |
| to access.</li> |
| <li><code>hal_omx_hwservice</code>. This is a HwBinder version of the |
| <code>mediacodec</code> Binder service, which apps are permitted to access.</li> |
| <li><code>hal_codec2_hwservice</code>. This is a newer version of |
| <code>hal_omx_hwservice</code>.</li> |
| </ul> |
| |
| <h4 id="useable-attributes">Useable attributes</h4> |
| <p> |
| All <code>hwservices</code> not considered safe have the attribute |
| <code>untrusted_app_visible_hwservice</code>. The corresponding HAL servers have |
| the attribute <code>untrusted_app_visible_halserver</code>. Devices launching |
| with Android P MUST NOT use either <code>untrusted</code> attribute. |
| </p> |
| <p> |
| Recommendation: |
| </p> |
| <ul> |
| <li>Untrusted apps should instead talk to a system service that talks to the |
| vendor HIDL HAL. For example, apps can talk to <code><a |
| href="https://android.googlesource.com/platform/system/sepolicy/+/master/public/app.te#209" |
| class="external">binderservicedomain</a></code>, then <code>mediaserver</code> |
| (which is a <code>binderservicedomain</code>) in turn talks to the <code><a |
| href="https://android.googlesource.com/platform/system/sepolicy/+/master/private/mediaserver.te#6" |
| class="external">hal_graphics_allocator</a></code>. |
| |
| <p><strong><em>OR</em></strong></p></li> |
| <li>Apps that need direct access to <code>vendor</code> HALs should have their |
| own vendor-defined sepolicy domain.</li> |
| </ul> |
| |
| <h3 id="file-attribute-tests">File attribute tests</h3> |
| <p> |
| Android 9 includes <a |
| href="https://android.googlesource.com/platform/system/sepolicy/+/master/tests/sepolicy_tests.py" |
| class="external">build time tests</a> that ensure all files in specific |
| locations have the appropriate attributes (such as, all files in |
| <code>sysfs</code> have the required <code>sysfs_type</code> attribute). |
| </p> |
| |
| |
| <h2 id="platform-public-policy">Platform-public policy</h2> |
| <p> |
| The platform-public policy is the core of conforming to the Android 8.0 |
| architecture model without simply maintaining the union of platform policies |
| from v1 and v2. Vendors are exposed to a subset of platform policy that |
| contains useable types and attributes and rules on those types and attributes |
| which then becomes part of vendor policy (i.e. |
| <code>vendor_sepolicy.cil</code>). |
| </p> |
| <p> |
| Types and rules are automatically translated in the vendor-generated policy |
| into <code>attribute_v<em>N</em></code> such that all platform-provided types |
| are versioned attributes (however attributes are not versioned). The platform is |
| responsible for mapping the concrete types it provides into the appropriate |
| attributes to ensure that vendor policy continues to function and that the rules |
| provided for a particular version are included. The combination of |
| platform-public policy and vendor policy satisfies the Android 8.0 architecture |
| model goal of allowing independent platform and vendor builds. |
| </p> |
| |
| <h3 id="mapping-to-attribute-chains">Mapping to attribute chains</h3> |
| <p> |
| When using attributes to map to policy versions, a type maps to an attribute or |
| multiple attributes, ensuring objects labeled with the type are accessible via |
| attributes corresponding to their previous types. |
| </p> |
| <p> |
| Maintaining a goal to hide version information from the policy writer means |
| automatically generating the versioned attributes and assigning them to the |
| appropriate types. In the common case of static types, this is straightforward: |
| <code>type_foo</code> maps to <code>type_foo_v1</code>. |
| </p> |
| <p> |
| For an object label change such as <code>sysfs</code> → <code>sysfs_A</code> or |
| <code>mediaserver</code> → <code>audioserver</code>, creating this mapping is |
| non-trivial (and is described in the examples above). Platform policy maintainers |
| must determine how to create the mapping at transition points for objects, which |
| requires understanding the relationship between objects and their assigned |
| labels and determining when this occurs. For backwards compatibility, this |
| complexity needs to be managed on the platform side, which is the only partition |
| that may uprev. |
| </p> |
| <h3 id="version-uprevs">Version uprevs</h3> |
| <p> |
| For simplicity, the Android platform releases an sepolicy version when a new |
| release branch is cut. As described above, the version number is contained in |
| <code>PLATFORM_SEPOLICY_VERSION</code> and is of the form <code>MM.nn</code>, |
| where <code>MM</code> corresponds to the SDK value and <code>nn</code> is a |
| private value maintained in<code> /platform/system/sepolicy.</code> For |
| example, <code>19.0</code> for Kitkat, <code>21.0</code> for Lollipop, |
| <code>22.0</code> for Lollipop-MR1 <code>23.0</code> for Marshmallow, |
| <code>24.0</code> for Nougat, <code>25.0</code> for Nougat-MR1, |
| <code>26.0</code> for Oreo, <code>27.0</code> for Oreo-MR1, and |
| <code>28.0</code> for Android P. Uprevs aren't always whole numbers. For |
| example, if an MR bump to a versions necessitates an incompatible change in |
| <code>system/sepolicy/public</code> but not an API bump, then that sepolicy |
| version could be: <code>vN.1</code>. The version present in a development |
| branch is a never-to-be-used-in-shipping-devices <code>10000.0</code>. |
| </p> |
| <p> |
| Android may deprecate oldest version when upreving. For input on when to |
| deprecate a version, Android may collect the number of devices with vendor |
| policies running that Android version and still receiving major platform |
| updates. If the number is less than a certain threshold, that version is |
| deprecated. |
| </p> |
| <h3 id="performance-impact-of-multiple-attributes">Performance impact of |
| multiple attributes</h3> |
| <p> |
| As described in <a |
| href="https://github.com/SELinuxProject/cil/issues/9" class="external">https://github.com/SELinuxProject/cil/issues/9</a>, |
| a large number of attributes assigned to a type result in performance issues in |
| the event of a policy cache miss. |
| </p> |
| <p> |
| This was confirmed to be an issue in Android, so <a |
| href="http://marc.info/?l=selinux&m=149202161421482&w=2" class="external">changes |
| were made</a> to Android 8.0 to remove attributes added to the policy by the |
| policy compiler, as well as to remove unused attributes. These changes resolved |
| performance regressions. |
| </p> |
| |
| |
| <h2 id="selinux-contexts-labeling">SELinux contexts labeling</h2> |
| <p>To support the distinction between platform and vendor sepolicy, |
| the system builds SELinux context files differently to keep them separate. |
| </p> |
| |
| <h3 id="file-contexts">File contexts</h3> |
| <p> |
| Android 8.0 introduced the following changes for <code>file_contexts</code>: |
| </p> |
| <ul> |
| <li>To avoid additional compilation overhead on device during boot, |
| <code>file_contexts</code> cease to exist in the binary form. Instead, they |
| are readable, regular expression text file such as <code>{property, |
| service}_contexts</code> (as they were pre-7.0).</li> |
| <li>The <code>file_contexts</code> are split between two files: |
| <ul> |
| <li><code>plat_file_contexts</code> |
| <ul> |
| <li>Android platform <code>file_context</code> that has no |
| device-specific labels, except for labeling parts of |
| <code>/vendor</code> partition that must be labeled precisely to |
| ensure proper functioning of the sepolicy files.</li> |
| <li>Must reside in <code>system</code> partition at |
| <code>/system/etc/selinux/plat_file_contexts</code> on device and |
| be loaded by <code>init</code> at the start along with the |
| vendor <code>file_context</code>.</li> |
| </ul> |
| </li> |
| <li><code>vendor_file_contexts</code> |
| <ul> |
| <li>Device-specific <code>file_context</code> built by combining |
| <code>file_contexts</code> found in the directories pointed to by |
| <code>BOARD_SEPOLICY_DIRS</code> in the device's |
| <code>Boardconfig.mk</code> files.</li> |
| <li>Must be installed at |
| <code>/vendor/etc/selinux/vendor_file_contexts</code> in |
| <code>vendor</code> partition and be loaded by <code>init</code> at |
| the start along with the platform <code>file_context</code>.</li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| |
| <h3 id="property-contexts">Property contexts</h3> |
| <p> |
| In Android 8.0, the <code>property_contexts</code> is split between two files: |
| </p> |
| <ul> |
| <li><code>plat_property_contexts</code> |
| <ul> |
| <li>Android platform <code>property_context</code> that has no |
| device-specific labels.</li> |
| <li>Must reside in <code>system</code> partition at |
| <code>/system/etc/selinux/plat_property_contexts</code> and be loaded |
| by <code>init</code> at the start along with the vendor |
| <code>property_contexts</code>.</li> |
| </ul> |
| </li> |
| <li><code>vendor_property_contexts</code> |
| <ul> |
| <li>Device-specific <code>property_context</code> built by combining |
| <code>property_contexts</code> found in the directories pointed to by |
| <code>BOARD_SEPOLICY_DIRS</code> in device's |
| <code>Boardconfig.mk</code> files.</li> |
| <li>Must reside in <code>vendor</code> partition at |
| <code>/vendor/etc/selinux/vendor_property_contexts</code> and be |
| loaded by <code>init</code> at the start along with the platform |
| <code>property_context</code></li> |
| </ul> |
| </li> |
| </ul> |
| |
| <h3 id="service-contexts">Service contexts</h3> |
| <p> |
| In Android 8.0, the <code>service_contexts</code> is split between the following |
| files: |
| </p> |
| <ul> |
| <li><code>plat_service_contexts</code> |
| <ul> |
| <li>Android platform-specific <code>service_context</code> for the |
| <code>servicemanager</code>. The <code>service_context</code> has no |
| device-specific labels.</li> |
| <li>Must reside in <code>system</code> partition at |
| <code>/system/etc/selinux/plat_service_contexts</code> and be loaded by |
| <code>servicemanager</code> at the start along with the vendor |
| <code>service_contexts</code>.</li> |
| </ul> |
| </li> |
| <li><code>vendor_service_contexts</code> |
| <ul> |
| <li>Device-specific <code>service_context</code> built by combining |
| <code>service_contexts</code> found in the directories pointed to by |
| <code>BOARD_SEPOLICY_DIRS</code> in the device's |
| <code>Boardconfig.mk</code> files.</li> |
| <li>Must reside in <code>vendor</code> partition at |
| <code>/vendor/etc/selinux/vendor_service_contexts</code> and be loaded |
| by <code>servicemanager</code> at the start along with the platform |
| <code>service_contexts</code>.</li> |
| <li>Although <code>servicemanager</code> looks for this file at boot time, |
| for a fully compliant <code>TREBLE</code> device, the |
| <code>vendor_service_contexts</code> MUST NOT exist. This is because |
| all interaction between <code>vendor</code> and <code>system</code> |
| processes MUST go through |
| <code>hwservicemanager</code>/<code>hwbinder</code>.</li> |
| </ul> |
| </li> |
| <li><code>plat_hwservice_contexts</code> |
| <ul> |
| <li>Android platform <code>hwservice_context</code> for |
| <code>hwservicemanager</code> that has no device-specific labels.</li> |
| <li>Must reside in <code>system</code> partition at |
| <code>/system/etc/selinux/plat_hwservice_contexts</code> and be loaded by |
| <code>hwservicemanager</code> at the start along with the |
| <code>vendor_hwservice_contexts</code>.</li> |
| </ul> |
| </li> |
| <li><code>vendor_hwservice_contexts</code> |
| <ul> |
| <li>Device-specific <code>hwservice_context</code> built by combining |
| <code>hwservice_contexts</code> found in the directories pointed to by |
| <code>BOARD_SEPOLICY_DIRS</code> in the device's |
| <code>Boardconfig.mk</code> files.</li> |
| <li>Must reside in <code>vendor</code> partition at |
| <code>/vendor/etc/selinux/vendor_hwservice_contexts</code> and be |
| loaded by <code>hwservicemanager</code> at the start along with the |
| <code>plat_service_contexts</code>.</li> |
| </ul> |
| </li> |
| <li><code>vndservice_contexts</code> |
| <ul> |
| <li>Device-specific <code>service_context</code> for the |
| <code>vndservicemanager</code> built by combining |
| <code>vndservice_contexts</code> found in the directories pointed to by |
| <code>BOARD_SEPOLICY_DIRS</code> in the device's |
| <code>Boardconfig.mk</code>.</li> |
| <li>This file must reside in <code>vendor</code> partition at |
| <code>/vendor/etc/selinux/vndservice_contexts</code> and be loaded by |
| <code>vndservicemanager</code> at the start.</li> |
| </ul> |
| </li> |
| </ul> |
| |
| <h3 id="seapp-contexts">Seapp contexts</h3> |
| <p> |
| In Android 8.0, the <code>seapp_contexts</code> is split between two files: |
| </p> |
| <ul> |
| <li><code>plat_seapp_contexts</code> |
| <ul> |
| <li>Android platform <code>seapp_context</code> that has no device-specific |
| changes.</li> |
| <li>Must reside in <code>system</code> partition at |
| <code>/system/etc/selinux/plat_seapp_contexts.</code></li> |
| </ul> |
| </li> |
| <li><code>vendor_seapp_contexts</code> |
| <ul> |
| <li>Device-specific extension to platform <code>seapp_context</code> built |
| by combining <code>seapp_contexts</code> found in the directories |
| pointed to by <code>BOARD_SEPOLICY_DIRS</code> in the device's |
| <code>Boardconfig.mk</code> files.</li> |
| <li>Must reside in <code>vendor</code> partition at |
| <code>/vendor/etc/selinux/vendor_seapp_contexts</code>.</li> |
| </ul> |
| </li> |
| </ul> |
| |
| <h3 id="mac-permissions">MAC permissions</h3> |
| <p> |
| In Android 8.0, the <code>mac_permissions.xml</code> is split between two files: |
| </p> |
| <ul> |
| <li>Platform <code>mac_permissions.xml</code> |
| <ul> |
| <li>Android platform <code>mac_permissions.xml</code> that has no |
| device-specific changes.</li> |
| <li>Must reside in <code>system</code> partition at |
| <code>/system/etc/selinux/.</code></li> |
| </ul> |
| </li> |
| <li>Non-Platform <code>mac_permissions.xml</code> |
| <ul> |
| <li>Device-specific extension to platform |
| <code>mac_permissions.xml</code> built from |
| <code>mac_permissions.xml</code> found in the directories pointed to by |
| <code>BOARD_SEPOLICY_DIRS</code> in the device's |
| <code>Boardconfig.mk</code> files.</li> |
| <li>Must reside in <code>vendor</code> partition at |
| <code>/vendor/etc/selinux/.</code></li> |
| </ul> |
| </li> |
| </ul> |
| |
| |
| </body> |
| </html> |