244 lines
12 KiB
HTML
244 lines
12 KiB
HTML
<html devsite>
|
||
<head>
|
||
<title>Implementing SELinux</title>
|
||
<meta name="project_path" value="/_project.yaml" />
|
||
<meta name="book_path" value="/_book.yaml" />
|
||
</head>
|
||
<body>
|
||
<!--
|
||
Copyright 2017 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
|
||
|
||
http://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>SELinux is set up to default-deny, which means that every single access for
|
||
which it has a hook in the kernel must be explicitly allowed by policy. This
|
||
means a policy file is comprised of a large amount of information regarding
|
||
rules, types, classes, permissions, and more. A full consideration of SELinux
|
||
is out of the scope of this document, but an understanding of how to write
|
||
policy rules is now essential when bringing up new Android devices. There is a
|
||
great deal of information available regarding SELinux already. See <a
|
||
href="/security/selinux#supporting_documentation">Supporting
|
||
documentation</a> for suggested resources.</p>
|
||
|
||
<h2 id=summary_of_steps>Summary of steps</h2>
|
||
|
||
<p>Here is a brief summary of the steps needed to implement SELinux on your
|
||
Android device:</p>
|
||
|
||
<ol>
|
||
<li>Add SELinux support in the kernel and configuration.
|
||
<li>Grant each service (process or daemon) started from <code>init</code> its own domain.
|
||
<li>Identify these services by:
|
||
<ul>
|
||
<li>Reviewing the init.<device>.rc file and finding all services.
|
||
<li>Examining warnings of the form <em>init: Warning! Service name needs a SELinux domain defined; please fix!</em> in <code>dmesg</code> output.
|
||
<li>Checking <code>ps -Z | grep init</code> output to see which services are running in the init domain.
|
||
</ul>
|
||
<li>Label all new processes, drivers, sockets, etc.
|
||
All objects need to be labeled
|
||
properly to ensure they interact properly with the policies you apply. See the
|
||
labels used in AOSP for examples to follow in label name creation.
|
||
<li>Institute security policies that fully cover all labels and restrict
|
||
permissions to their absolute minimum.
|
||
</ol>
|
||
|
||
<p>Ideally, OEMs start with the policies in the AOSP and then build upon them for
|
||
their own customizations.</p>
|
||
|
||
<h2 id=key_files>Key files</h2>
|
||
|
||
<p>SELinux for Android is accompanied by everything you need to enable SELinux
|
||
now. You merely need to integrate the <a href="https://android.googlesource.com/kernel/common/">latest Android kernel</a> and then incorporate the files found in the <a href="https://android.googlesource.com/platform/system/sepolicy/">system/sepolicy</a> directory:</p>
|
||
|
||
<p><a href="https://android.googlesource.com/kernel/common/">https://android.googlesource.com/kernel/common/ </a></p>
|
||
|
||
<p><a href="https://android.googlesource.com/platform/system/sepolicy/">https://android.googlesource.com/platform/system/sepolicy/</a></p>
|
||
|
||
<p>Those files when compiled comprise the SELinux kernel security policy and cover
|
||
the upstream Android operating system. You should not need to modify the
|
||
system/sepolicy files directly. Instead, add your own device-specific policy
|
||
files within the /device/manufacturer/device-name/sepolicy directory.</p>
|
||
|
||
<p>Here are the files you must create or edit in order to implement SELinux:</p>
|
||
|
||
<ul>
|
||
<li><em>New SELinux policy source (*.te) files</em> - Located in the
|
||
<root>/device/manufacturer/device-name/sepolicy directory. These files define
|
||
domains and their labels. The new policy files get
|
||
concatenated with the existing policy files during compilation into a single
|
||
SELinux kernel policy file.
|
||
<p class="caution"><strong>Important:</strong> Do not alter the app.te file
|
||
provided by the Android Open Source Project.
|
||
Doing so risks breaking all third-party applications.</p>
|
||
<li><em>Updated BoardConfig.mk makefile</em> - Located in the <device-name>
|
||
directory containing the sepolicy subdirectory. It must be updated to reference
|
||
the sepolicy subdirectory once created if it
|
||
wasn’t in initial implementation.
|
||
<li><em>file_contexts</em> - Located in the sepolicy subdirectory. This file
|
||
assigns labels to files and is used by various userspace components. As you
|
||
create new policies, create or update this file to
|
||
assign new labels to files. In order to apply new file_contexts, you must
|
||
rebuild the filesystem image or run <code>restorecon</code> on the file to be
|
||
relabeled. On upgrades, changes to file_contexts are automatically applied to
|
||
the system and userdata partitions as part of the upgrade. Changes can also be
|
||
automatically applied on upgrade to other partitions by adding
|
||
restorecon_recursive calls to your init.<em>board</em>.rc file after the
|
||
partition has been mounted read-write.
|
||
<li><em>genfs_contexts</em> - Located in the sepolicy subdirectory. This file
|
||
assigns labels to filesystems such as proc or vfat that do not support extended
|
||
attributes. This configuration is loaded as part of the kernel policy but
|
||
changes may not take effect for in-core inodes, requiring a reboot or
|
||
unmounting and re-mounting the filesystem to fully apply the change. Specific
|
||
labels may also be assigned to specific mounts such as vfat using the context=
|
||
mount option.
|
||
<li><em>property_contexts</em> - Located in the sepolicy subdirectory. This
|
||
file assigns labels to Android system properties to control what processes can
|
||
set them. This configuration is read by the init process during startup.
|
||
<li><em>service_contexts</em> - Located in the sepolicy subdirectory. This
|
||
file assigns labels to Android binder services to control what processes can
|
||
add (register) and find (lookup) a binder reference for the service. This
|
||
configuration is read by the servicemanager process during startup.
|
||
<li><em>seapp_contexts</em> - Located in the sepolicy subdirectory. This file
|
||
assigns labels to app processes and /data/data directories. This configuration
|
||
is read by the zygote process on each app launch and by installd during
|
||
startup.
|
||
<li><em>mac_permissions.xml</em> - Located in the sepolicy subdirectory. This
|
||
file assigns a seinfo tag to apps based on their signature and optionally their
|
||
package name. The seinfo tag can then be used as a key in the seapp_contexts
|
||
file to assign a specific label to all apps with that seinfo tag. This
|
||
configuration is read by system_server during startup.
|
||
</ul>
|
||
|
||
<p>Then just update your BoardConfig.mk makefile - located in the directory
|
||
containing the sepolicy subdirectory - to reference the sepolicy subdirectory
|
||
and each policy file once created, as shown below. The BOARD_SEPOLICY variables
|
||
and their meaning is documented in the system/sepolicy/README file.</p>
|
||
|
||
<pre class="devsite-click-to-copy">
|
||
BOARD_SEPOLICY_DIRS += \
|
||
<root>/device/manufacturer/device-name/sepolicy
|
||
|
||
BOARD_SEPOLICY_UNION += \
|
||
genfs_contexts \
|
||
file_contexts \
|
||
sepolicy.te
|
||
</pre>
|
||
|
||
<p class="note"><strong>Note:</strong> As of the M release,
|
||
BOARD_SEPOLICY_UNION is no longer required as all policy files found within any
|
||
directory included in the BOARD_SEPOLICY_DIRS variable are joined with the
|
||
base policy automatically.</p>
|
||
|
||
<p>After rebuilding your device, it is enabled with SELinux. You can now either
|
||
customize your SELinux policies to accommodate your own additions to the
|
||
Android operating system as described in <a
|
||
href="customize.html">Customization</a> or verify your existing setup as
|
||
covered in <a href="validate.html">Validation</a>.</p>
|
||
|
||
<p>Once the new policy files and BoardConfig.mk updates are in place, the new
|
||
policy settings are automatically built into the final kernel policy file.</p>
|
||
|
||
<h2 id=use_cases>Use cases</h2>
|
||
|
||
<p>Here are specific examples of exploits to consider when crafting your own
|
||
software and associated SELinux policies:</p>
|
||
|
||
<p><strong>Symlinks</strong> - Because symlinks appear as files, they are often read just as that. This can
|
||
lead to exploits. For instance, some privileged components such as init change
|
||
the permissions of certain files, sometimes to be excessively open.</p>
|
||
|
||
<p>Attackers might then replace those files with symlinks to code they control,
|
||
allowing the attacker to overwrite arbitrary files. But if you know your
|
||
application will never traverse a symlink, you can prohibit it from doing so
|
||
with SELinux.</p>
|
||
|
||
<p><strong>System files</strong> - Consider the class of system files that should only be modified by the
|
||
system server. Still, since netd, init, and vold run as root, they can access
|
||
those system files. So if netd became compromised, it could compromise those
|
||
files and potentially the system server itself.</p>
|
||
|
||
<p>With SELinux, you can identify those files as system server data files.
|
||
Therefore, the only domain that has read/write access to them is system server.
|
||
Even if netd became compromised, it could not switch domains to the system
|
||
server domain and access those system files although it runs as root.</p>
|
||
|
||
<p><strong>App data</strong> - Another example is the class of functions that must run as root but should
|
||
not get to access app data. This is incredibly useful as wide-ranging
|
||
assertions can be made, such as certain domains unrelated to application data
|
||
being prohibited from accessing the internet.</p>
|
||
|
||
<p><strong>setattr</strong> - For commands such as chmod and chown, you could identify the set of files
|
||
where the associated domain can conduct setattr. Anything outside of that could
|
||
be prohibited from these changes, even by root. So an application might run
|
||
chmod and chown against those labeled app_data_files but not shell_data_files
|
||
or system_data_files.</p>
|
||
|
||
<h2 id=steps_in_detail>Steps in detail</h2>
|
||
|
||
<p>Here is a detailed view of how Android recommends you employ and customize
|
||
SELinux to protect your devices:</p>
|
||
|
||
<ol>
|
||
<li>Enable SELinux in the kernel:
|
||
<code>CONFIG_SECURITY_SELINUX=y</code>
|
||
<li>Change the kernel_cmdline parameter so that:<br/>
|
||
<pre class="devsite-click-to-copy">
|
||
BOARD_KERNEL_CMDLINE := androidboot.selinux=permissive
|
||
</pre>
|
||
<br/>
|
||
This is only for initial development of policy for the device. Once you have
|
||
an initial bootstrap policy, remove this parameter so that your device is
|
||
enforcing or it will fail CTS.
|
||
<li>Boot up the system in permissive and see what denials are encountered on boot:<br/>
|
||
On Ubuntu 14.04 or newer:
|
||
<br/>
|
||
<pre class="devsite-terminal devsite-click-to-copy">
|
||
adb shell su -c dmesg | grep denied | audit2allow -p out/target/product/<var>BOARD</var>/root/sepolicy
|
||
</pre>
|
||
<br/>
|
||
On Ubuntu 12.04:<br/>
|
||
<pre class="devsite-terminal devsite-click-to-copy">
|
||
adb shell su -c dmesg | grep denied | audit2allow
|
||
</pre>
|
||
<li>Evaluate the output. See <a href="validate.html">Validation</a> for instructions and tools.
|
||
<li>Identify devices, and other new files that need labeling.
|
||
<li>Use existing or new labels for your objects.
|
||
Look at the *_contexts files to
|
||
see how things were previously labeled and use knowledge of the label meanings
|
||
to assign a new one. Ideally, this will be an existing label which will fit
|
||
into policy, but sometimes a new label will be needed, and rules for access to
|
||
that label will be needed, as well.
|
||
<li>Identify domains/processes that should have their own security domains. A policy will likely need to be written for each of these from scratch. All services spawned from <code>init</code>, for instance, should have their own. The following commands help reveal those that remain running (but ALL services need such a treatment):<br/>
|
||
<pre class="devsite-terminal devsite-click-to-copy">
|
||
adb shell su -c ps -Z | grep init
|
||
</pre>
|
||
<pre class="devsite-terminal devsite-click-to-copy">
|
||
adb shell su -c dmesg | grep 'avc: '
|
||
</pre>
|
||
<li>Review init.<device>.rc to identify any which are without a type.
|
||
These should
|
||
be given domains EARLY in order to avoid adding rules to init or otherwise
|
||
confusing <code>init</code> accesses with ones that are in their own policy.
|
||
<li>Set up <code>BOARD_CONFIG.mk</code> to use <code>BOARD_SEPOLICY_*</code> variables. See
|
||
the README in system/sepolicy for details on setting this up.
|
||
<li> Examine the init.<device>.rc and fstab.<device> file and make sure every use of “mount”
|
||
corresponds to a properly labeled filesystem or that a context= mount option is specified.
|
||
<li> Go through each denial and create SELinux policy to properly handle each. See
|
||
the examples within <a href="customize.html">Customization</a>.
|
||
</ol>
|
||
|
||
</body>
|
||
</html>
|