Google has rewritten the pvmfm firmware used in Android in Rust.

As part of efforts to strengthen the security of critical software components of the Android platform, Google has rewritten the pvmfm firmware used for organizing the operation of virtual machines launched by the pVM hypervisor from the Android Virtualization Framework in Rust. Previously, the firmware was written in C and implemented on top of the U-Boot bootloader, which had previously been found to contain vulnerabilities due to memory handling issues.

The rewritten Rust firmware is included in Android 14, and the universal libraries created during the firmware development process are packaged as crates and handed over to the Rust community. For instance, the smccc package has been published to support ARM interfaces like PSCI (Power State Coordination Interface) and SMCCC (SMC Calling Convention) calls, and the aarch64-paging package for manipulating memory page tables. Additionally, efforts have been made to fix bugs and expand the functionality of the existing virtio-drivers package with the implementation of VirtIO drivers. Beyond the Android platform, these packages are utilized in the Oak project, which develops components for secure data transmission, storage, and processing in Trusted Execution Environments (TEE).

The pVM hypervisor takes control at an early stage of booting and ensures complete memory isolation. of virtual machines and host environments, preventing the host system from accessing the secure virtual machines handling confidential data. The pvmfm firmware (Protected Virtual Machine Firmware) takes control immediately after the virtual machine starts, verifies the formed environment, and decides whether to abort the boot process in case of integrity issues or generates a boot certificate for the guest system if the trust chain is confirmed.

Reworking in Rust allows for simpler and safer adherence to Google's 'two rules' for maintaining the security of Android's system components. According to this rule, any added code must meet no more than two out of three conditions: working with untrusted input, using unsafe programming languages (C/C++), and executing with elevated privileges. The implication of this rule is that code handling external data should either be restricted to minimal privileges (isolated) or be written in a safe programming language. According to Google statistics, around 70% of all dangerous vulnerabilities identified in Android are caused by memory errors.

Rust focuses on safe memory management and reduces the risk of vulnerabilities caused by issues such as accessing memory after it has been freed and buffer overflows. Safe memory handling in Rust is ensured at compile time through reference checking, ownership tracking of objects, and accounting for the lifetimes (scope) of objects, as well as evaluating memory access correctness during code execution. Rust also provides tools for protection against integer overflows, requires mandatory initialization of variable values before use, better handles errors in the standard library, employs the concept of immutability for references and variables by default, and offers strong static typing to minimize logical errors.

Challenges that arise during the development of low-level components in Rust, such as drivers, include the necessity of working with raw pointers in unsafe mode, as Rust is designed with an emphasis on memory management allocated in the program. In code that operates without abstraction layers over the hardware, one must interact with shared memory and MMIO. Currently, Rust's capabilities for working with raw pointers leave much to be desired, but the situation is expected to improve after the stabilization of support for the macros offset_of, slice_ptr_get, and slice_ptr_len.

Among the drawbacks, it is also worth noting the need for improved syntax to access structure fields and array indices through raw pointers without creating references, as well as limitations in creating safe wrappers over unsafe operations that can lead to undefined behavior and cannot be checked by the compiler. For example, such wrappers cannot be created for operations with memory page tables, as page mapping in one part of the program can impact other parts.

Regarding the size of the resulting code, the old version of the pVM firmware occupied 220 kB, while the new one took up 460 kB. However, the rewritten version included new features that allowed for the removal of some other components used during boot. As a result, the total size of all old and new boot components turned out to be comparable. It is noted that when size is more important than performance, comparable results to the C language can be achieved by enabling additional size optimization modes in the compiler, eliminating unnecessary dependencies, and avoiding string formatting tools.

Additionally, the continuation of work on implementing the capability to run trusted applications (Trusted Applications) written in Rust within the Trusty operating system is mentioned. Trusty provides a Trusted Execution Environment (TEE) for Android, running in parallel with Android on the same processor in a separate isolated environment. Trusty is used in Pixel devices and already utilizes Rust in its libraries and system components (the kernel remains in C).

Source: opennet.ru

Buy reliable website hosting with DDoS protection, VPS VDS servers 🔥 Buy reliable website hosting with DDoS protection, VPS VDS servers | ProHoster