| <html devsite> |
| <head> |
| <title>Building SELinux Policy</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 covers how SELinux policy is built. SELinux policy is built from |
| the combination of core AOSP policy (platform) and device-specific policy |
| (vendor). The SELinux policy build flow for Android 4.4 through Android |
| 7.0 merged all sepolicy fragments then generated monolithic files in the root |
| directory. This meant that SoC vendors and ODM manufacturers modified boot.img |
| (for non-A/B devices) or system.img (for A/B devices) every time policy was |
| modified. |
| </p> |
| <p> |
| In Android 8.0 and higher, platform and vendor policy is built separately. |
| SOCs and OEMs can update their parts of the policy, build their images |
| (vendor.img, boot.img, etc.), then update those images independent of platform |
| updates. |
| </p> |
| <p> |
| However, as modularized SELinux policy files are stored on <code>/vendor</code> |
| partitions, the <code>init</code> process must mount the system and vendor |
| partitions earlier so it can read SELinux files from those partitions and merge |
| them with core SELinux files in the system directory (before loading them into |
| the kernel). |
| </p> |
| |
| <h2 id="files">Source files</h2> |
| <p> |
| The logic for building SELinux is in these files: |
| </p> |
| <ul> |
| <li><a href="https://android.googlesource.com/platform/external/selinux/" class="external"> |
| <code>external/selinux</code></a>: External SELinux project, used to |
| build HOST command line utilities to compile SELinux policy and labels. |
| <ul> |
| <li><a href="https://android.googlesource.com/platform/external/selinux/libselinux" class="external"> |
| <code>external/selinux/libselinux</code></a>: Android uses only a subset |
| of the external <code>libselinux</code> project along with some |
| Android-specific customizations. For details, see |
| <a href="https://android.googlesource.com/platform/external/selinux/+/master/README.android" class="external"> |
| <code>external/selinux/README.android</code></a>.</li> |
| <li><a href="https://android.googlesource.com/platform/external/selinux/+/master/libsepol/" class="external"> |
| <code>external/selinux/libsepol</code></a>: |
| <ul> |
| <li><a href="http://man7.org/linux/man-pages/man8/chkcon.8.html"i class="external"> |
| <code>chkcon</code></a>: Determine if a security context is valid |
| for a given binary policy (host executable).</li> |
| <li><a href="https://android.googlesource.com/platform/external/selinux/+/master/libsepol/" class="external"> |
| <code>libsepol</code></a>: SELinux library for manipulating binary |
| security policies (host static/shared library, target static library).</li> |
| </ul> |
| </li> |
| <li><a href="https://android.googlesource.com/platform/external/selinux/+/master/checkpolicy/" class="external"> |
| <code>external/selinux/checkpolicy</code></a>: SELinux policy compiler |
| (host executables: <code>checkpolicy</code>, <code>checkmodule</code>, |
| and <code>dispol</code>). Depends on <code>libsepol</code>.</li> |
| </ul> |
| </li> |
| <li><a href="https://android.googlesource.com/platform/system/sepolicy/+/master" class="external"> |
| <code>system/sepolicy</code></a>: Core Android SELinux policy |
| configurations, including contexts and policy files. Major sepolicy build |
| logic is also here (<code>system/sepolicy/Android.mk</code>).</li> |
| </ul> |
| <p> |
| For more details on the files in <code>system/sepolicy</code> |
| <a href="/security/selinux/implement#key_files">Implementing SELinux</a>. |
| </p> |
| |
| <h2 id="android-7">Android 7.0 and earlier</h2> |
| |
| <p>This section covers how SELinux policy is built in Android 7.x and earlier.</p> |
| |
| <h3 id="android-7-building">Building SELinux policy</h3> |
| <p> |
| SELinux policy is created by combining the core AOSP policy with device-specific |
| customizations. The combined policy is then passed to the policy compiler and |
| various checkers. Device-specific customization is done through the |
| <code>BOARD_SEPOLICY_DIRS</code> variable defined in device-specific |
| <code>Boardconfig.mk</code> file. This global build variable contains a list of |
| directories that specify the order in which to search for additional policy files. |
| </p> |
| <p> |
| For example, a SoC vendor and an ODM might each add a directory, one for the |
| SoC-specific settings and another for device-specific settings, to generate the |
| final SELinux configurations for a given device: |
| </p> |
| <ul> |
| <li><code>BOARD_SEPOLICY_DIRS += device/<var>SOC</var>/common/sepolicy</code></li> |
| <li><code>BOARD_SEPOLICY_DIRS += device/<var>SoC</var>/<var>DEVICE</var>/sepolicy</code></li> |
| </ul> |
| <p> |
| The content of file_contexts files in <code>system/sepolicy</code> and |
| <code>BOARD_SEPOLICY_DIRS</code> are concatenated to generate the |
| <code>file_contexts.bin</code> on the device: |
| </p> |
| |
| <figure> |
| <img src="images/n-selinux-build-logic.png" |
| alt="This image shows the SELinux build logic for Android 7.x."> |
| <figcaption><strong>Figure 1</strong>. SELinux build logic</figcaption> |
| </figure> |
| <p> |
| The <code>sepolicy</code> file consists of multiple source files: |
| </p> |
| <ul> |
| <li>The plain text <code>policy.conf</code> is generated by concatenating |
| <code>security_classes</code>, <code>initial_sids</code>, |
| <code>*.te</code> files, <code>genfs_contexts</code>, and |
| <code>port_contexts</code> in that order.</li> |
| <li>For each file (such as <code>security_classes</code>), its content is the |
| concatenation of the files with the same name under |
| <code>system/sepolicy/</code> and <code>BOARDS_SEPOLICY_DIRS</code>.</li> |
| <li>The <code>policy.conf</code> is sent to SELinux compiler for syntax |
| checking and compiled into binary format as <code>sepolicy</code> on the |
| device. |
| <figure> |
| <img src="images/n-selinux-policy-file.png" |
| alt="This image shows the files that generate the SELinux policy file |
| for Android 7.x."> |
| <figcaption><strong>Figure 2</strong>. SELinux policy file</figcaption> |
| </figure></li> |
| </ul> |
| |
| <h3 id="selinux-files">SELinux files</h3> |
| <p> |
| After compiling, Android devices running 7.x and earlier typically contain the |
| following SELinux-related files: |
| </p> |
| <ul> |
| <li><code>selinux_version</code></li> |
| <li><code>sepolicy: binary output after combining policy files (security_classes, |
| initial_sids, *.te, etc.)</code></li> |
| <li><code>file_contexts</code></li> |
| <li><code>property_contexts</code></li> |
| <li><code>seapp_contexts</code></li> |
| <li><code>service_contexts</code></li> |
| <li><code>system/etc/mac_permissions.xml</code></li> |
| </ul> |
| <p> |
| For more details, see <a href="/security/selinux/implement">Implementing SELinux</a>. |
| </p> |
| <h3 id="android-n-init">SELinux initialization</h3> |
| <p> |
| When the system boots up, SELinux is in permissive mode (and not in enforcing |
| mode). The init process performs the following tasks: |
| </p> |
| <ul> |
| <li>Loads <code>sepolicy</code> files from ramdisk into the kernel through |
| <code>/sys/fs/selinux/load</code>.</li> |
| <li>Switches SELinux to enforcing mode.</li> |
| <li>Re-exec()s itself to apply the SELinux domain rule to itself.</li> |
| </ul> |
| <p> |
| To shorten the boot time, perform the <code>re-exec()</code> on the |
| <code>init</code> process as soon as possible. |
| </p> |
| |
| <h2 id="android-o">Android 8.0 and higher</h2> |
| <p> |
| In Android 8.0, SELinux policy is split into platform and vendor |
| components to allow independent platform/vendor policy updates while |
| maintaining compatibility. |
| </p> |
| <p> |
| The platform sepolicy is further split into platform private and platform public |
| parts to export specific types and attributes to vendor policy writers. |
| The platform public types/attributes are guaranteed to be maintained as stable |
| APIs for a given platform version. Compatibility with previous platform public |
| types/attributes can be guaranteed for several versions using platform mapping |
| files. |
| </p> |
| <h3 id="platform-public">Platform public sepolicy</h3> |
| <p> |
| The platform public sepolicy includes everything defined under |
| <a href="https://android.googlesource.com/platform/system/sepolicy/+/master/public/" class="external"> |
| <code>system/sepolicy/public</code></a>. The platform can assume the types and |
| attributes defined under public policy are stable APIs for a given platform |
| version. This forms the part of the sepolicy that is exported by platform on |
| which vendor (i.e. device) policy developers may write additional |
| device-specific policy. |
| </p> |
| <p> |
| Types are versioned according to the version of the policy that vendor |
| files are written against, defined by the <code>PLATFORM_SEPOLICY_VERSION</code> |
| build variable. The versioned public policy is then included with the |
| vendor policy and (in its original form) in the platform policy. Thus, |
| the final policy includes the private platform policy, the current platform's |
| public sepolicy, the device-specific policy, and the versioned public policy |
| corresponding to the platform version against which the device policy was |
| written. |
| </p> |
| <h3 id="platform-private">Platform private sepolicy</h3> |
| <p> |
| The platform private sepolicy includes everything defined under |
| <a href="https://android.googlesource.com/platform/system/sepolicy/+/master/private" class="external"> |
| <code>/system/sepolicy/private</code></a>. This part of the policy forms |
| platform-only types, permissions, and attributes required for platform |
| functionality. These are not exported to the <code>vendor/device</code> policy |
| writers. Non-platform policy writers must not write their policy extensions |
| based on types/attributes/rules defined in platform private sepolicy. Moreover, |
| these rules are allowed to be modified or may disappear as part of a |
| framework-only update. |
| </p> |
| <h3 id="platform-private-mapping">Platform private mapping</h3> |
| <p> |
| The platform private mapping includes policy statements that map the attributes |
| exposed in platform public policy of the previous platform versions to the |
| concrete types used in current platform public sepolicy. This ensures |
| vendor policy that was written based on platform public attributes from |
| the previous platform public sepolicy version(s) continues to work. The |
| versioning is based on the <code>PLATFORM_SEPOLICY_VERSION</code> build variable |
| set in AOSP for a given platform version. A separate mapping file exists for |
| each previous platform version from which this platform is expected to accept |
| vendor policy. For more details, see |
| <a href="/security/selinux/compatibility">Compatibility</a>. |
| </p> |
| <h2 id="android-o-build">Building SELinux policy</h2> |
| <p> |
| SELinux policy in Android 8.0 is made by combining pieces from |
| <code>/system</code> and <code>/vendor</code>. Logic for setting this up |
| appropriately is in |
| <a href="https://android.googlesource.com/platform/system/sepolicy/+/master/Android.mk" class="external"> |
| <code>/platform/system/sepolicy/Android.mk</code></a>. |
| </p> |
| <p> |
| Policy exists in the following locations: |
| </p> |
| <table> |
| <tr> |
| <th>Location</th> |
| <th>Contains</th> |
| </tr> |
| <tr> |
| <td><code>system/sepolicy/public</code></td> |
| <td>The platform's sepolicy API</td> |
| </tr> |
| <tr> |
| <td><code>system/sepolicy/private</code></td> |
| <td>Platform implementation details (vendors can ignore)</td> |
| </tr> |
| <tr> |
| <td><code>system/sepolicy/vendor</code></td> |
| <td>Policy and context files that vendors can use (vendors can ignore if desired)</td> |
| </tr> |
| <tr> |
| <td><code>BOARD_SEPOLICY_DIRS</code></td> |
| <td>Vendor sepolicy</td> |
| </tr> |
| </table> |
| |
| <p> |
| The build system takes this policy and produces platform and vendor |
| policy components on the system partition and vendor partition, respectively. |
| Steps include: |
| </p> |
| <ol> |
| <li>Converting policies to the SELinux Common Intermediate Language (CIL) |
| format, specifically: |
| <ol> |
| <li>public platform policy</li> |
| <li>combined private + public policy</li> |
| <li>public + vendor and <code>BOARD_SEPOLICY_DIRS</code> policy</li> |
| </ol> |
| </li> |
| <li>Versioning the policy provided by public as part of the vendor policy. |
| Done by using the produced public CIL policy to inform the combined public + |
| vendor + <code>BOARD_SEPOLICY_DIRS</code> policy as to which parts must be |
| turned into attributes that will be linked to the platform policy.</li> |
| <li>Creating a mapping file linking the platform and vendor parts. |
| Initially, this just links the types from the public policy with the |
| corresponding attributes in the vendor policy; later it will also provide |
| the basis for the file maintained in future platform versions, enabling |
| compatibility with vendor policy targeting this platform version.</li> |
| <li>Combining policy files (describe both on-device and precompiled solutions). |
| <ol> |
| <li>Combine mapping, platform and vendor policy.</li> |
| <li>Compile output binary policy file.</li> |
| </ol> |
| </li> |
| </ol> |
| |
| </body> |
| </html> |