| <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="key_files">Key files</h2> |
| |
| <p>To enable SELinux, integrate the |
| <a href="https://android.googlesource.com/kernel/common/" class="external">latest |
| Android kernel</a> and then incorporate the files found in the |
| <a href="https://android.googlesource.com/platform/system/sepolicy/" class="external">system/sepolicy</a> |
| directory. When compiled, those files comprise the SELinux kernel security |
| policy and cover the upstream Android operating system.</p> |
| <p>In general, you should not modify the <code>system/sepolicy</code> files |
| directly. Instead, add or edit your own device-specific policy files in the |
| <code>/device/<var>manufacturer</var>/<var>device-name</var>/sepolicy</code> |
| directory. In Android 8.0 and higher, the changes you make to these files should |
| only affect policy in your vendor directory. For more details on separation of |
| public sepolicy in Android 8.0 and higher, see |
| <a href="/security/selinux/customize#android-o">Customizing SEPolicy in Android |
| 8.0+</a>. Regardless of Android version, you're still modifying these files:</p> |
| |
| |
| <h3 id="policy-files">Policy files</h3> |
| |
| <p>Files that end with <code>*.te</code> are SELinux policy source files, which |
| define domains and their labels. You may need to create new policy files in |
| <code>/device/<var>manufacturer</var>/<var>device-name</var>/sepolicy</code>, |
| but you should try to update existing files where possible.</p> |
| |
| <h3 id="context-files">Context files</h3> |
| <p>Context files are where you specify labels for your objects.</p> |
| <ul> |
| <li><code>file_contexts</code> 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. To apply new <code>file_contexts</code>, |
| rebuild the filesystem image or run <code>restorecon</code> on the file to |
| be relabeled. On upgrades, changes to <code>file_contexts</code> 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 <code>restorecon_recursive</code> calls to your |
| init.<var>board</var>.rc file after the partition has been mounted |
| read-write.</li> |
| <li><code>genfs_contexts</code> assigns labels to filesystems, such as |
| <code>proc</code> or <code>vfat</code> 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 |
| <code>vfat</code> using the <code>context=mount</code> option.</li> |
| <li><code>property_contexts</code> assigns labels to Android system properties to |
| control what processes can set them. This configuration is read by the |
| <code>init</code> process during startup.</li> |
| <li><code>service_contexts</code> 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 |
| <code>servicemanager</code> process during startup.</li> |
| <li><code>seapp_contexts</code> assigns labels to app processes and |
| <code>/data/data</code> directories. This configuration is read by the |
| <code>zygote</code> process on each app launch and by <code>installd</code> |
| during startup.</li> |
| <li><code>mac_permissions.xml</code> assigns a <code>seinfo</code> tag to apps |
| based on their signature and optionally their package name. The |
| <code>seinfo</code> tag can then be used as a key in the |
| <code>seapp_contexts</code> file to assign a specific label to all apps with |
| that <code>seinfo</code> tag. This configuration is read by |
| <code>system_server</code> during startup.</li> |
| </ul> |
| |
| <h3 id="boardconfig">BoardConfig.mk makefile</h3> |
| |
| <p>After editing or adding policy and context files, update your |
| <code>/device/<var>manufacturer</var>/<var>device-name</var>/BoardConfig.mk</code> |
| makefile to reference the <code>sepolicy</code> subdirectory and each new policy file. |
| For more information about the <code>BOARD_SEPOLICY</code> variables, see |
| <a href="https://android.googlesource.com/platform/system/sepolicy/+/master/README" class="external"> |
| <code>system/sepolicy/README</code> file</a>.</p> |
| |
| <pre class="devsite-click-to-copy"> |
| BOARD_SEPOLICY_DIRS += \ |
| <root>/device/<var>manufacturer</var>/<var>device-name</var>/sepolicy |
| |
| BOARD_SEPOLICY_UNION += \ |
| genfs_contexts \ |
| file_contexts \ |
| sepolicy.te |
| </pre> |
| |
| <p>After rebuilding, your device 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="/security/selinux/customize.html">Customization</a> or verify your |
| existing setup as covered in |
| <a href="/security/selinux/validate.html">Validation</a>.</p> |
| |
| <p>When the new policy files and BoardConfig.mk updates are in place, the new |
| policy settings are automatically built into the final kernel policy file. |
| For more information about how sepolicy is built on the device, see |
| <a href="security/selinux/building">Building sepolicy</a>.</p> |
| |
| <h2 id="steps">Implementation</h2> |
| |
| <p>To get started with SELinux:</p> |
| |
| <ol> |
| <li>Enable SELinux in the kernel: |
| <code>CONFIG_SECURITY_SELINUX=y</code></li> |
| <li>Change the kernel_cmdline parameter so that: |
| <pre class="devsite-click-to-copy"> |
| BOARD_KERNEL_CMDLINE := androidboot.selinux=permissive</pre> |
| This is only for initial development of policy for the device. After you |
| have an initial bootstrap policy, remove this parameter so your |
| device is enforcing or it will fail CTS.</li> |
| <li>Boot up the system in permissive and see what denials are encountered on boot:<br/> |
| On Ubuntu 14.04 or newer: |
| <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> |
| On Ubuntu 12.04: |
| <pre class="devsite-terminal devsite-click-to-copy"> |
| adb pull /sys/fs/selinux/policy |
| adb logcat -b all | audit2allow -p policy |
| </pre></li> |
| <li>Evaluate the output for warnings that resemble <code>init: Warning! |
| Service name needs a SELinux domain defined; please fix!</code> See |
| <a href="/security/selinux/validate">Validation</a> for instructions |
| and tools.</li> |
| <li>Identify devices, and other new files that need labeling.</li> |
| <li>Use existing or new labels for your objects. Look at the |
| <code>*_contexts</code> 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. Add your labels to the appropriate context files.</li> |
| <li>Identify domains/processes that should have their own security domains. |
| You will likely need to write a completely new policy for each. 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> |
| <li>Review <code>init.<var>device</var>.rc</code> to identify any domains that |
| don't have a domain type. Give them a domain <em>early</em> in your |
| development process to avoid adding rules to <code>init</code> or |
| otherwise confusing <code>init</code> accesses with ones that are in their |
| own policy.</li> |
| <li>Set up <code>BOARD_CONFIG.mk</code> to use <code>BOARD_SEPOLICY_*</code> |
| variables. See the |
| <a href="https://android.googlesource.com/platform/system/sepolicy/+/master/README" class="external">README</a> |
| in <code>system/sepolicy</code> for details on setting this up.</li> |
| <li>Examine the init.<var>device</var>.rc and fstab.<var>device</var> file and |
| make sure every use of <code>mount</code> corresponds to a properly |
| labeled filesystem or that a <code>context= mount</code> option is |
| specified.</li> |
| <li>Go through each denial and create SELinux policy to properly handle each. See |
| the examples in <a href="/security/selinux/customize">Customization</a>. |
| </ol> |
| |
| <p>You should start with the policies in the AOSP and then build upon them for |
| your own customizations. For more information about policy strategy and a |
| closer look at some of these steps, see |
| <a href="/security/selinux/device-policy">Writing SELinux Policy</a>.</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 as files, which can lead to exploits. For instance, some privileged |
| components, such as <code>init</code>, 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 be modified only by the system server. Still, since <code>netd</code>, |
| <code>init</code>, and <code>vold</code> run as root, they can access |
| those system files. So if <code>netd</code> 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 <code>netd</code> 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 <code>chmod</code> and |
| <code>chown</code>, you could identify the set of files where the associated |
| domain can conduct <code>setattr</code>. Anything outside of that could be |
| prohibited from these changes, even by root. So an application might run |
| <code>chmod</code> and <code>chown</code> against those labeled |
| <code>app_data_files</code> but not <code>shell_data_files</code> |
| or <code>system_data_files</code>.</p> |
| |
| </body> |
| </html> |