If you’re the type of person who uses the word “vuln” as a shorthand for code vulnerabilities, you should check out the presentation from the recent Linux Security Summit called “Security in Zephyr and Fuchsia.” In the talk, two researchers from the National Security Agency discuss their contributions to the nascent security stacks of two open source OS projects: Zephyr and Fuchsia.
If you’re worried about the fact that Edward Snowden’s old employer is helping to write next generation OSes that could run our lives in 10 years, consider the upsides. First, since these are open source projects, any nefarious backdoors would be clearly visible. Second, the NSA knows a thing or two about security. Stephen Smalley and James Carter, who discussed security in Zephyr and Fuchsia, respectively, are computer security researchers at the NSA’s Information Assurance Research group, which developed and maintains the security-enhanced SELinux and SE Android distributions. Smalley leads the NSA’s Security Enhancements (SE) for the Internet of Things project and is a kernel and userspace maintainer for SELinux.
The Linux Foundation hosted Zephyr Project, which is creating the IoT-oriented Zephyr RTOS, is the more mature of the two projects. Google’s Fuchsia OS has a longer way to go — especially if you believe that Fuchsia will replace Android and Chrome OS over the next decade.
The developers of Zephyr and Fuchsia have a rare opportunity to develop novel, up-to-date security stacks from scratch. One of the main reasons Google chose to build Fuchsia from a new microkernel was that it could avoid the hodgepodge of legacy code layered on top of Linux, thereby improving security. Attempts to boost security in Linux are always going to be like patching holes in a boat. Zephyr and Fuchsia aim to be the OS equivalents of hovercraft.
Zephyr and Fuchsia are very different OSes, and they implement security in different ways. Zephyr is designed for constrained devices running on microcontrollers, such as Cortex-M4 chips, whereas Fuchsia will target phones and desktops running on applications processors, such as Cortex-A53 and Intel Core.
“Zephyr and Fuchsia were both open sourced in 2016, but they have been developed for very different use cases,” said Smalley. “Their architectures are very different, and each is also very different from Linux.”
Like Linux and Fuchsia, Zephyr has RO/NX memory protection, stack depth overflow prevention, and stack buffer overflow detection. However, there’s still no kernel or user space ASLR (address space layout randomization), which “will likely move to a build time randomization and a small boot time relocation,” said Smalley.
Among other architectural differences with Linux, “There’s no process isolation in Zephyr, only a userspace thread model,” explained Smalley. “The process abstraction model has yet to be implemented, and the kernel/user boundary is still being fleshed out.”
In Zephyr, “you’re generally working with a single application, and security is highly dependent on particular SoCs and kernel configurations,” said Smalley. By comparison, “In Linux, there are a number of core OS security features that are neutral and independent.”
The original Zephyr release had a single executable with a single address space with all threads in supervisor mode and no memory protection or virtual memory, said Smalley. “As Zephyr added OS protections, it sought to minimize changes to kernel APIs in order to be backward compatible,” he added. “A key Zephyr design philosophy is to do as much as possible at build time, and then as much as possible at last view time, thereby minimizing runtime overheads and ensuring bounded latency for real-time.”
Zephyr security is complicated by the fact that some of the MCUs it targets include memory protection units (MPUs) while others do not. Beginning in releases 1.8 and 1.9, Zephyr began to provide memory protections, with allowances for both types of MCUs.
The NSA team developed a set of kernel memory protection tests modeled on lkdtm tests from the Kernel Self Protection Project (KSPP) for Linux. “The tests were helpful in catching bugs in Zephyr MPU drivers, and they are now used for regression testing,” said Smalley.
Zephyr added userspace support in versions 1.10 and 1.11 that provided basic support for user mode threads with isolated memory. Smalley’s team developed a set of userspace tests “that sought to validate the security properties for user mode threads were being enforced.” Zephyr’s userspace memory model is still limited to a single executable and address space, and there’s no virtual memory. “It can support user mode threads but not full processes,” explained Smalley.
Sign up to receive updates on Open Source Summit and ELC+OpenIoT Europe:
Zephyr security features include an object permissions model in which user threads must first be granted permissions to an object to enable access. “A kernel mode thread can grant access to a user mode thread, and an inheritance mechanism allows those permissions to be propagated down,” explained Smalley. “It’s an all or nothing model — all user threads can access all app global variables.”
This all-or-nothing approach “poses a high burden on the application developer, who has to manually organize the application global variable memory layout to meet MPU restrictions,” said Smalley. To help compensate, the NSA team developed a feature due in release 1.13 that “supports a slightly more developer friendly way of grouping application globals based on desired protections. It’s a small step forward, not a panacea.”
Future Zephyr security work includes adding MPU virtualization, which “would allow us to support a larger number of regions instead of just eight that can be swapped in and out of the MPU on demand,” said Smalley. “We also hope to provide full support for multiple applications and program loading.”
In Zephyr, kernel code is fully trusted. “We would like to see Linux-like mitigations for kernel vulns using KSPP kernel self-protection features while minimizing runtime overheads,” said Smalley. Other wish-list items include leveraging armv8-m for Cortex-M MCUs, thereby enabling TrustZone security. There’s also a long-term plan to “develop a MAC suited to RTOSes that’s more oriented to build-time app partitioning.”
Fuchsia differs from Linux and Zephyr in that it’s a microkernel OS with security based on object capability. Like Linux it offers process isolation. In addition, “The plumbing for kernel or user space ASLR is there,” said the NSA’s James Carter.
Compared to the “large and monolithic” Linux, Fuchsia has a small, decomposed TCB (trusted computing base),” said Carter. “It also uses object capabilities instead of DAC and MAC.”
Fuchsia is based on the Zircon Microkernel, which is derived from the little kernel (lk), “an RTOS used in the Android bootloader,” explained Carter. Fuchsia extends lk to support 64-bit, user mode, processes, IPC, and other advanced features. “The lk is the only thing that runs in supervisor mode. Drivers, filesystem, and network all run in user mode.”
Fuchsia security mechanisms include regular handles and resource handles using Zircon object capabilities. “Regular handles are usually the only way that userspace can access kernel objects,” said Carter. “Fuchsia differs from most OSes in that it uses a push model in which a client creates the handle and pushes it to a server. Handles are per-process and unforgeable, and they identify both the object and a set of access rights to the object. Access rights include duplicating them with equal or lesser rights or passing them across IPC or using them to obtain handles to child objects with equal or lesser writes.”
Fuchsia handles “are good because they separate rights for propagation vs. use and separate rights for different operations,” said Carter. “You can also reduce rights through handle duplication.”
Handles still pose some problems, however. For example, “with object_get_child(), if you have a handle to a job, you can acquire a handle to anything in that job or any child jobs,” said Carter. “Also, a leak of root job handle is fatal to security. We’d like to see more work on making everything able to be least privilege, and more control over handle propagation and revocation. Not all operations currently check access rights and some rights are unimplemented.”
Resource handles, which are the type of handle used for platform resources like memory mapped I/O, I/O ports, and IRQs, let developers specify the type of resource and optional range. On the plus side, they offer “fine-grained, hierarchical resource restrictions,” said Carter. “However, right now the root resource check isn’t very granular, and as with regular handles, leaks can be fatal. We need to work on propagation, revocation, and refining to least privilege.”
Zircon security primitives include job policy and vDSO enforcement. “In Fuchsia everything is part of a job,” said Carter. “Processes don’t have child processes – jobs have child jobs. Jobs can be nested, containing jobs and other processes, and job policy is applied to all processes within the job. Policies are inherited from the parent and can only be made more restrictive.”
On the pro side, you can create fine-grained object creation policies, as well as hierarchical job policies that are mixed,” explained Carter. “However, the W^X policy is not yet implemented, and when it is it will cause problems with strict hierarchical policies because if a child needs to map something W^X, then all ancestors would need to beta map it W^X as well.”
In Fuchsia, the vDSO (virtual dynamic shared object) primitive “is only meant to invoke system calls,” said Carter. “It’s fully read-only and is mapping constrained by the kernel.”
Fuchsia’s vDSO makes the OS more secure by “limiting the kernel attack surface, enforcing the use of the public API, and supporting per process system call restrictions,” said Carter. “It’s also good that vDSO is not trusted by the kernel so its system call arguments are fully validated.” On the other hand, the current version offers the potential for tampering with or bypassing vDSO, added Carter.
Carter went on to explain Fuchsia namespaces and sandboxes. Advantages of the namespaces implementation include “the lack of a global namespace and the fact that object reachability is determined by initial namespace,” said Carter. “But we’d like to see more granularity.” For sandboxes, which are used for isolating applications, “We’d like to see an expansion to system services. There’s also no independent validation of the sandbox configuration.”
As with Zephyr, the NSA team recommends that Fuchsia eventually add a MAC framework, which would help to “control propagation, support revocation, and apply least privilege,” said Carter. “A MAC could support finer grained check and generalize job policy, as well as validate namespaces and sandboxes. It could also provide a unified framework for defining, enforcing, and validating security goals.”
Options for integrating a MAC with Fuchsia start with building it entirely in user space with no microkernel support, said Carter. Alternatively, you could “extend the existing mechanism” by building it “mostly in user space with limited microkernel support.” A third choice would be to “create security policy logic in user space with full microkernel enforcement for its objects, as we did with DTMach in SELinux.”
In conclusion, Carter emphasized that Fuchsia’s security stack is a work in progress. “We’re just trying to evaluate the thing.” You can watch the entire video below.