| <html devsite> |
| <head> |
| <title>Validating 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>Android strongly encourages OEMs to test their SELinux implementations |
| thoroughly. As manufacturers implement SELinux, they should apply the new |
| policy to a test pool of devices first.</p> |
| |
| <p>After applying a new policy, make sure SELinux is running in the correct |
| mode on the device by issuing the command <code>getenforce</code>.</p> |
| |
| <p>This prints the global SELinux mode: either Enforcing or Permissive. To |
| determine the SELinux mode for each domain, you must examine the corresponding |
| files or run the latest version of <code>sepolicy-analyze</code> with the |
| appropriate (<code>-p</code>) flag, present in |
| <a href="https://android.googlesource.com/platform/system/sepolicy/+/master/tools/" class="external"> |
| <code>/platform/system/sepolicy/tools/</code></a>.</p> |
| |
| <h2 id="reading_denials">Reading denials</h2> |
| |
| <p>Check for errors, which are routed as event logs to <code>dmesg</code> |
| and <code>logcat</code> and are viewable locally on the device. Manufacturers |
| should examine the SELinux output to <code>dmesg</code> on these devices and |
| refine settings prior to public release in permissive mode and eventual switch |
| to enforcing mode. SELinux log messages contain <code>avc:</code> and so may |
| easily be found with <code>grep</code>. It is possible to capture the ongoing |
| denial logs by running <code>cat /proc/kmsg</code> or to capture denial logs |
| from the previous boot by running |
| <code>cat /sys/fs/pstore/console-ramoops</code>.</p> |
| |
| <p>With this output, manufacturers can readily identify when system users or |
| components are in violation of SELinux policy. Manufacturers can then repair |
| this bad behavior, either by changes to the software, SELinux policy, or both.</p> |
| |
| <p>Specifically, these log messages indicate what processes would fail under |
| enforcing mode and why. Here is an example:</p> |
| |
| <pre> |
| avc: denied { connectto } for pid=2671 comm="ping" path="/dev/socket/dnsproxyd" |
| scontext=u:r:shell:s0 tcontext=u:r:netd:s0 tclass=unix_stream_socket |
| </pre> |
| |
| <p>Interpret this output like so:</p> |
| |
| <ul> |
| <li> The <code>{ connectto }</code> above represents the action being taken. Together with the |
| <code>tclass</code> at the end (<code>unix_stream_socket</code>), it tells you roughly what was being done |
| to what. In this case, something was trying to connect to a unix stream socket. |
| <li> The <code>scontext (u:r:shell:s0)</code> tells you what context initiated the action. In |
| this case this is something running as the shell. |
| <li> The <code>tcontext (u:r:netd:s0)</code> tells you the context of the action’s target. In |
| this case, that’s a unix_stream_socket owned by <code>netd</code>. |
| <li> The <code>comm="ping"</code> at the top gives you an additional hint about what was being |
| run at the time the denial was generated. In this case, it’s a pretty good hint. |
| </ul> |
| |
| <p>Another example:</p> |
| <pre class="devsite-terminal devsite-click-to-copy">adb shell su root dmesg | grep 'avc: '</pre> |
| <p>Output:</p> |
| <pre> |
| <5> type=1400 audit: avc: denied { read write } for pid=177 |
| comm="rmt_storage" name="mem" dev="tmpfs" ino=6004 scontext=u:r:rmt:s0 |
| tcontext=u:object_r:kmem_device:s0 tclass=chr_file |
| </pre> |
| |
| |
| <p>Here are the key elements from this denial:</p> |
| |
| <ul> |
| <li><em>Action</em> - the attempted action is highlighted in brackets, |
| <code>read write</code> or <code>setenforce</code>. |
| <li><em>Actor</em> - The <code>scontext</code> (source context) entry represents |
| the actor, in this case the<code> rmt_storage</code> daemon. |
| <li><em>Object</em> - The <code>tcontext</code> (target context) entry represents |
| the object being acted upon, in this case kmem. |
| <li><em>Result</em> - The <code>tclass</code> (target class) entry indicates the type |
| of object being acted upon, in this case a <code>chr_file</code> (character device). |
| </ul> |
| |
| <h2 id=switching_to_permissive>Switching to permissive</h2> |
| |
| <p class="caution"><strong>Important:</strong> Permissive mode is not supported |
| on production devices. CTS tests confirm |
| enforcing mode is enabled.</p> |
| |
| <p>SELinux enforcement can be disabled via ADB on userdebug or eng builds. To do so, |
| first switch ADB to root by running <code>adb root</code>. Then, to disable SELinux |
| enforcement, run: |
| <pre class="devsite-terminal devsite-click-to-copy"> |
| adb shell setenforce 0 |
| </pre> |
| |
| <p>Or at the kernel command line (during early device bring-up):</p> |
| |
| <pre class="devsite-click-to-copy"> |
| <code class="devsite-terminal">androidboot.selinux=permissive</code> |
| <code class="devsite-terminal">androidboot.selinux=enforcing</code> |
| </pre> |
| |
| <h2 id=using_audit2allow>Using audit2allow</h2> |
| |
| <p>The <code>selinux/policycoreutils/audit2allow</code> tool takes |
| <code>dmesg</code> denials and converts them into corresponding SELinux policy |
| statements. As such, it can greatly speed SELinux development. |
| <code>audit2allow</code> is shipped as part of the Android source tree and |
| is compiled automatically when you build Android from source.</p> |
| |
| <p>To use it, run:</p> |
| |
| <pre class="devsite-click-to-copy"> |
| <code class="devsite-terminal">adb pull /sys/fs/selinux/policy</code> |
| <code class="devsite-terminal">adb logcat -b all -d | audit2allow -p policy</code> |
| </pre> |
| |
| <p class="note"><strong>Note</strong>: Running these commands does not change |
| bugreport.txt because all logs are already there, including the ones from |
| before the last reboot. On devices running an OTA or development flash, old |
| and new violations are mixed until another reboot. To address this, reboot |
| the device again or filter console-ramoops and LAST_LOGCAT from your bugreport. |
| </p> |
| |
| <p>Nevertheless, care must be taken to examine each potential addition for |
| overreaching permissions. For example, feeding audit2allow the |
| <code>rmt_storage</code> denial shown earlier results in the following |
| suggested SELinux policy statement:</p> |
| |
| <pre> |
| #============= shell ============== |
| allow shell kernel:security setenforce; |
| #============= rmt ============== |
| allow rmt kmem_device:chr_file { read write }; |
| </pre> |
| |
| |
| <p>This would grant <code>rmt</code> the ability to write kernel memory, a |
| glaring security hole. Often the <code>audit2allow</code> statements are only a |
| starting point. After employing these statements, you may need to change the |
| source domain and the label of the target, as well as incorporate proper |
| macros, to arrive at a good policy. Sometimes the denial being examined should |
| not result in any policy changes at all; rather the offending application |
| should be changed.</p> |
| |
| </body> |
| </html> |