| <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> |