Zygote
Securitynerd

Memory safety and Rust

Most of Android's worst vulnerabilities were the same bug in different clothes: C or C++ code reading memory it did not own. The response was layered hardening, and then a language change.

12 minAPI 1–37 · 17interactivequizverified 2026-10-27

The most common sentence in an Android security bulletin, historically, was some variation of "a use-after-free in a C or C++ component". The platform's response has been one of the more interesting security projects of the last decade, because it combined hardening, mitigation and, finally, a different language.

TL;DR#

  • bugs — use-after-free, buffer overflow, out-of-bounds read — were the majority of Android's severe vulnerabilities for most of its history.
  • Defences came in waves: allocator hardening, , , and on newer Arm hardware.
  • The structural fix is : new platform code is written in a memory-safe language where the compiler rejects the bug class.
  • Google reported that by 2022 the memory-safety share of vulnerabilities had fallen to 35%, down from 76% in 2019 — the first year it was not a majority.
  • Isolation is the other half: even a memory bug in a media codec is contained by the sandbox and SELinux.

Mental model#

Think of a workshop where the tools can hurt you.

In a C workshop, every saw has no guard and every blade is exposed. A skilled carpenter never gets hurt, and the workshop's safety record depends on skill. Add guards (hardening), add a first-aid kit (isolation), and add inspections (fuzzing), and the injury rate falls — but it never reaches zero, because the tools are still sharp.

A Rust workshop has tools that refuse to cut the carpenter. The guards are in the tool, checked at build time. That does not make the carpenter safe from every injury — they can still drop a hammer on their foot — but it removes the category of injury the tools were causing.

Where the analogy breaks#

Rust's guarantees cover safe Rust. unsafe blocks exist, FFI boundaries are unconstrained, and logic errors (an authorisation check that is wrong) are not memory-safety bugs at all. A Rust workshop still has a few sharp tools in a locked cabinet, and the cabinet is opened more often than the marketing suggests.

The big picture#

Loading diagram…
Text description of this diagram

The security onion. Memory safety is not a ring; it is a property of the code inside the kernel and sandbox rings. The kernel ring's description notes that it is mostly C, which is why memory-safety work matters there. The app sandbox ring is the containment strategy: a memory bug in a sandboxed process is a bug in a process that can reach almost nothing.

The diagram's real message is positional: memory safety is not a boundary you can add. It is a property of the code, and the platform's strategy has been to contain the code that lacks it and replace the code that most needs it.

Deep dive#

The bug class#

Three shapes account for most of the damage:

  • Use-after-free. Memory is freed, a pointer to it survives, and something writes through it. The write lands in whatever now occupies that memory — often another object's vtable.
  • Out-of-bounds read/write. An index or length is wrong, and access goes past the end of a buffer.
  • Integer overflow leading to a short allocation. A size calculation wraps, a buffer is allocated too small, and a copy overflows it.

All three are memory errors, not logic errors. All three are rejected by a compiler that tracks ownership and bounds. None of them can be found reliably by review, which is why the industry's answer moved from "write more carefully" to "change the language".

The hardening waves#

Each wave addresses a different part of the problem.

Allocator hardening. Android's allocator (Scudo) adds checks: metadata integrity, quarantine of freed chunks, and randomised placement. A use-after-free that would silently corrupt now often crashes instead. That converts an exploitable bug into a crash — which is a security improvement even though it is not a fix.

Control-flow integrity. CFI checks that indirect calls and returns land on valid targets. Many memory-corruption exploits work by overwriting a function pointer or a return address and redirecting control; CFI makes that redirect fail. Android enables it broadly on arm64 system code and in the kernel.

seccomp. A syscall filter reduces the kernel surface a compromised process can reach. It does not prevent memory bugs, but it limits what a memory bug can be turned into.

MTE. Arm's Memory Tagging Extension attaches a small tag to each allocation and to each pointer, and checks them on every access.1 A use-after-free or an out-of-bounds access with the wrong tag faults immediately. Android supports MTE for developers and, on newer hardware, more broadly.

Rust in AOSP#

The structural fix is to stop writing new memory-unsafe code. AOSP supports Rust as a first-class platform language, with build rules, bindings and a growing set of components.

The reported results, from Google's December 2022 post on memory-safe languages in Android 13:

  • Memory-safety vulnerabilities fell from 223 in 2019 to 85 in 2022.2
  • As a share of all Android vulnerabilities, they fell from 76% to 35%.
  • 2022 was the first year in which memory-safety bugs were not the majority.
  • About 21% of all new native code in Android 13 was Rust — roughly 1.5 million lines in AOSP.

Those numbers are the strongest available evidence that the language change is doing what it was supposed to do. They are also a reminder that the effect is slow: a codebase of tens of millions of lines changes composition over years, not releases.

Where Rust is used#

The components that have moved are chosen for a reason: they parse untrusted input and they are reachable from the network or from other apps.

  • Keystore2, the keystore daemon (Android 12), which parses key blobs and requests.
  • The Bluetooth stack, which has a long history of remotely reachable memory bugs.
  • UWB, the ultra-wideband stack.
  • DNS-over-HTTP3 and parts of the networking stack.
  • The Android Virtualization Framework, where isolation is the point.
  • The kernel, via Rust for Linux, for new drivers.

That list is a good summary of the selection criteria: untrusted input, high reachability, and a component that is being written or rewritten anyway.

The cost#

Rust is not free, and the costs are real:

  • Build times. Rust compilation is slower, and AOSP's build is already slow.
  • Binary size. Rust binaries tend to be larger, which matters on low-end devices.
  • Interop. Every call across the FFI boundary is unsafe, and the boundary is where the bugs move to.
  • Hiring and review. Fewer engineers are fluent in Rust, and review practices for unsafe code are less mature than for C.

The platform's judgement is that these costs are smaller than the cost of the bug class. The vulnerability numbers support that judgement.

The containment strategy#

The other half of the answer does not require changing any code: make the bug's blast radius small.

That is what the media and networking architecture does. A codec runs in a sandboxed process with a narrow SELinux domain. A WebView renderer runs in an isolated process. A media extractor runs in mediaserver rather than in your app.

The Stagefright bugs are the canonical example of why this matters. A set of memory-corruption bugs in media parsing was reachable by simply receiving an MMS. The response was not only to fix the bugs but to restructure the media stack so that a parsing bug is contained: the codecs moved into their own processes, the parsers became sandboxed, and the media components became Mainline modules that can be patched out of cycle.

How it evolved#

Security and privacy changes7 releases
APIVersionWhat changed
184.3 Jelly Bean
  • App Ops (hidden) introduced for permission control
236.0 Marshmallow
  • requestPermissions() and the runtime permission flow
289 Pie
  • Foreground service permission
3011
  • One-time permissions
3112
  • Bluetooth scan/connect permissions
3313 Tiramisu
  • POST_NOTIFICATIONS runtime permission
3717 Cinnamon Bun
  • ACCESS_LOCAL_NETWORK runtime permission for local network access

The timeline in five points: allocator hardening and ASLR (early), CFI (Android 8 onward), seccomp for apps (8.0), Rust support (10 onward), MTE (newer Arm hardware). The language change is the youngest and the slowest, and it is the one with the clearest durable effect.

Under the hood#

  • Rust crates used by the platform
  • a large Rust daemon in a security-critical path
  • the Bluetooth stack, with Rust components
  • the C library: the largest remaining memory-unsafe surface in every process

Curiosity corner#

  • The 2019 baseline matters. 76% of vulnerabilities being memory-safety bugs is not a scandal; it is what a large C/C++ codebase looks like. The interesting number is the direction of travel.
  • MTE is a hardware feature that needs software support. A device can have the extension and not use it; Android's support is opt-in for developers and increasingly on by default on newer hardware.
  • The Bluetooth stack's Rust rewrite is partly a response to specific bugs. Remote, unauthenticated memory corruption in a radio stack is the worst kind of bug, and it justified a rewrite.

Try it#

See what the platform reports about itself

adb shell getprop ro.product.cpu.abilist adb shell getprop ro.debuggable adb shell getprop ro.build.type adb shell dumpsys package com.android.bluetooth | head -20

ro.build.type is user on a production device, userdebug on an engineering build. MTE is typically enabled for development builds and on hardware that supports it in production.

Check yourself#

Check yourself

1 / 12

Which layer enforces the app sandbox?

0 answered · 0 correct

Sources#

Sources

Every version number, API level, class name and date on this page is traced to one of these. Pages are re-verified against them; last_verified above says when.

  1. docsMemory safetysource.android.comaccessed 2026-10-27↩
  2. blogMemory-safe languages in Android 13Google Security Blogaccessed 2026-10-27↩
  3. docsAndroid Rust modulessource.android.comaccessed 2026-10-27↩
  4. docsAndroid Rust patternssource.android.comaccessed 2026-10-27↩
  5. docsSeccomp BPFdocs.kernel.orgaccessed 2026-10-27↩
  6. docsAndroid Compatibility Definition Document (CDD)source.android.comaccessed 2026-10-27↩
  7. docsCompatibility Test Suite (CTS)source.android.comaccessed 2026-10-27↩