Hardening the Kernel in Android Oreo
Posted by Sami Tolvanen, Senior Software Engineer, Android Security
The hardening of Android's userspace has increasingly made the underlying Linux
kernel a more attractive target to attackers. As a result, more than a third of
Android security bugs were found in the kernel last year. In Android 8.0 (Oreo),
significant effort has gone into hardening the kernel to reduce the number and
impact of security bugs.
href="https://android-developers.googleblog.com/2016/07/protecting-android-with-more-linux.html">Android
Nougat worked to protect the kernel by isolating it from userspace processes
with the addition of SELinux ioctl filtering and requiring seccomp-bpf support,
which allows apps to filter access to available system calls when processing
untrusted input. Android 8.0 focuses on kernel self-protection with four
security-hardening features backported from upstream Linux to all Android
kernels supported in devices that first ship with this release.
Hardened usercopy
Usercopy functions are used by the kernel to transfer data from user space to
kernel space memory and back again. Since 2014, missing or invalid bounds
checking has caused about 45% of Android's kernel vulnerabilities. href="https://lwn.net/Articles/695991/">Hardened usercopy adds bounds
checking to usercopy functions, which helps developers spot misuse and fix bugs
in their code. Also, if obscure driver bugs slip through, hardening these
functions prevents the exploitation of such bugs.
This feature href="https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f5509cc18daa7f82bcc553be70df2117c8eedc16">was
introduced in the upstream kernel version 4.8, and we have backported it to
Android kernels 3.18 and above.
int buggy_driver_function(void __user *src, size_t size)
{
/* potential size_t overflow (don’t do this) */
u8 *buf = kmalloc(size * N, GPF_KERNEL);
…
/* results in buf smaller than size, and a heap overflow */
if (copy_from_user(buf, src, size))
return -EFAULT;
/* never reached with CONFIG_HARDENED_USERCOPY=y */
}
An example of a security issue that hardened usercopy prevents.
Privileged Access Never (PAN) emulation
While hardened usercopy functions help find and mitigate security issues, they
can only help if developers actually use them. Currently, all kernel code,
including drivers, can access user space memory directly, which can lead to
various security issues.
To mitigate this, CPU vendors have introduced features such as Supervisor Mode
Access Prevention (SMAP) in x86 and Privileged Access Never (PAN) in ARM v8.1.
These features prevent the kernel from accessing user space directly and ensure
developers go through usercopy functions. Unfortunately, these hardware features
are not yet widely available in devices that most Android users have today.
Upstream Linux introduced software emulation for PAN in kernel version href="https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit?id=a5e090acbf545c0a3b04080f8a488b17ec41fe02">4.3
for ARM and 4.10 in ARM64. We
have backported both features to Android kernels starting from 3.18.
Together with hardened usercopy, PAN emulation has helped find and fix bugs in
four kernel drivers in Pixel devices.
int buggy_driver_copy_data(struct mydata *src, void __user *ptr)
{
/* failure to keep track of user space pointers */
struct mydata *dst = (struct mydata *)ptr;
…
/* read/write from/to an arbitrary user space memory location */
dst->field = … ; /* use copy_(from|to)_user instead! */
…
/* never reached with PAN (emulation) or SMAP */
}
An example of a security issue that PAN emulation mitigates.
Kernel Address Space Layout Randomization (KASLR)
Android has included support for Address Space Layout Randomization (ASLR) for
years. Randomizing memory layout makes code reuse attacks probabilistic and
therefore more difficult for an attacker to exploit, especially remotely.
Android 8.0 brings this feature to the kernel. While Linux has supported href="https://lwn.net/Articles/569635/">KASLR on x86 since version 3.14, href="https://lwn.net/Articles/673598/">KASLR for ARM64 has only been
available upstream since Linux 4.6. Android 8.0 makes KASLR available in Android
kernels 4.4 and newer.
KASLR helps mitigate kernel vulnerabilities by randomizing the location where
kernel code is loaded on each boot. On ARM64, for example, it adds 13–25 bits of
entropy depending on the memory configuration of the device, which makes code
reuse attacks more difficult.
Post-init read-only memory
The final hardening feature extends existing memory protections in the kernel by
creating a memory region that's marked read-only after the kernel has been
initialized. This makes it possible for developers to improve protection on data
that needs to be writable during initialization, but shouldn't be modified after
that. Having less writable memory reduces the internal attack surface of the
kernel, making exploitation harder.
Post-init read-only memory was
introduced in upstream kernel version 4.6 and we have backported it to Android
kernels 3.18 and newer. While we have applied these protections to some data
structures in the core kernel, this feature is extremely useful for developers
working on kernel drivers.
Conclusion
Android Oreo includes mitigations for the most common source of security bugs in
the kernel. This is especially relevant because 85% of kernel security bugs in
Android have been in vendor drivers that tend to get much less scrutiny. These
updates make it easier for driver developers to discover common bugs during
development, stopping them before they can reach end user devices.
Komentar
Posting Komentar