blob: 0fe7cf01b1b15c31bb05a6a80a715a7a8690d653 [file] [log] [blame]
<html devsite>
<head>
<title>Kernel Control Flow Integrity</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>
<a href="https://clang.llvm.org/docs/ControlFlowIntegrity.html">Control flow
integrity</a> (CFI) is a security mechanism that disallows changes to the
original control flow graph of a compiled binary, making it significantly harder
to perform such attacks.
</p>
<p>
In Android 9, we enabled LLVM's implementation of CFI in more components and
also in the kernel. <a href="/devices/tech/debug/cfi">System CFI</a> is on by
default, but you need to enable kernel CFI.
</p>
<p>
LLVM's CFI requires compiling with <a
href="https://llvm.org/docs/LinkTimeOptimization.html">Link-Time Optimization
(LTO)</a>. LTO preserves the LLVM bitcode representation of object files until
link-time, which allows the compiler to better reason about what optimizations
can be performed. Enabling LTO reduces the size of the final binary and improves
performance, but increases compile time. In testing on Android, the combination
of LTO and CFI results in negligible overhead to code size and performance; in a
few cases both improved.
</p>
<p>
For more technical details about CFI and how other forward-control checks are
handled, see the <a
href="https://clang.llvm.org/docs/ControlFlowIntegrityDesign.html">LLVM design
documentation</a>.
</p>
<h2 id="implementation">Implementation</h2>
<p>
Support for kernel CFI exists in Android common kernel versions 4.9 and 4.14. If
your kernel is based on version 4.9 or 4.14 and you build with Clang, then you
can enable it. To enable kCFI, you need to copy over the relevant patches and
update your kernel config file.
</p>
<h3 id="copy-kcfi-patches">Copy kCFI patches</h3>
<p>
Add these changes to your kernel:
</p>
<ul>
<li><a
href="https://android-review.googlesource.com/q/topic:android-4.9-cfi">Version
4.9</a></li>
<li><a
href="https://android-review.googlesource.com/q/topic:android-4.14-cfi">Version
4.14</a></li>
</ul>
<h3 id="enable-kcfi">Enable kCFI</h3>
<p>
After you've copied over the relevant changes, you need to enable the kCFI in
your kernel config file, such as
<code>/kernel/<var>PROJECT</var>/+/<var>BRANCH</var>/arch/arm64/configs/<var>PROJECT</var>_defconfig</code>.
</p>
<p>
To enable kCFI, add these lines:
</p>
<pre class="prettyprint">CONFIG_LTO_CLANG=y
CONFIG_CFI_CLANG=y</pre>
<h3 id="troubleshooting">Troubleshooting</h3>
<p>
After enabling, work through any type mismatch errors that may exist with their
drivers. An indirect function call through an incompatible function pointer
trips CFI. When a CFI failure is detected, the kernel prints out a warning that
includes both the function that was called and the stacktrace that led to the
failure. Correct this by ensuring function pointers always have the same type as
the function that's called.
</p>
<p>
To assist in debugging CFI failures, enable <code>CONFIG_CFI_PERMISSIVE</code>,
which prints out a warning instead of causing a kernel panic. Permissive mode
must not be used in production.
</p>
<h2 id="validation">Validation</h2>
<p>
Currently, there are no CTS test specifically for CFI. Instead, make sure that
CTS tests pass with or without CFI enabled to verify that CFI isn't impacting
the device.
</p>
</body>
</html>