blob: 62b23aa5eaef719019fb169c460292c1edadea0d [file] [log] [blame]
<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>