• Announcements
  • Information on CFI in GrapheneOS and response to a paper

Android uses Clang type-based forward edge Control Flow Integrity (CFI) for the kernel and a subset of userspace. It isn't a high impact security feature. We used to have changes expanding userspace coverage but Android is already doing it and we moved this effort to higher impact work.

Unlike Chrome, we enable type-based forward edge CFI for our Vanadium browser to cover the default browser and WebView. Other than that, the usage of Clang CFI has the same scope as the stock Pixel OS and our focus is on higher impact areas. Expanding it causes regressions we have to address.

Unlike the stock Pixel OS, we enable branch target identification (BTI) to address holes in Clang CFI coverage in the kernel and the lack of full deployment in userspace. BTI is coarse grained CFI and is an extremely weak security feature but it's easy to enable and doesn't cause regressions.

Unlike the stock Pixel OS, we enable pointer authentication (PAC) return protection for userspace instead of only the kernel. Similar to BTI, this is easy to enable and doesn't cause regressions. Unlike the stock Pixel OS, we use Shadow Call Stack as an extra layer on top of PAC in the kernel.

Instead of working on expanding CFI coverage, our focus is on higher impact features including hardware memory tagging (MTE). We have a best-in-class implementation of MTE for heap protection in hardened_malloc and we deploy MTE for all but a single userspace process (camera HAL).

Our most recent release enabled MTE for the Linux kernel allocators too: https://grapheneos.org/releases#2025011500. We need to improve the kernel implementation to enforce deterministic guarantees with it as hardened_malloc does. We're also planning to deploy stack allocation MTE for both the kernel and userspace.

MTE directly uncovers memory corruption bugs which are often security bugs. Type-based CFI uncovers type mismatches which block deploying it but rarely have any direct security impact. These are major ongoing areas of work as software changes, not only for the initial deployment.

The recently published paper "Twenty years later: Evaluating the Adoption of Control Flow Integrity" has major inaccuracies due to flaws in their tools and methodology. They inaccurately claim we don't expand coverage of CFI and wrongly claim we reduce it on end-of-life 4th/5th gen Pixels.

4th/5th gen Pixels are end-of-life. We make it clear that our releases for them are unofficial extended support releases for harm reduction. Regardless, we do not reduce CFI coverage on them. We also don't increase the number of executable code as they claim but rather greatly reduce it.

They didn't look into what was actually happening and resulting in their tools reporting what they are. Their claims are likely based on the way we handle device support ending up placing the same executables and libraries in more locations. They also miss a whole lot including Chromium.

The paper also wrongly portrays largely ending up with the same end result for compiled code on devices where there aren't major differences such as PAC and BTI as us reusing the code from the stock OS. No, that's not what is happening. Android builds are reproducible. That's not reuse.

The paper describes Android 13 is the most recent release of Android and lists releases from April 2023 as what they analyzed, so there's also the issue of it being very outdated. This does not explain the inaccuracies, but does partially explain why it doesn't cover PAC and BTI.

There are other inaccuracies including about GrapheneOS but we don't need to go through all of it point by point. We'll be contacting the authors asking for corrections but our expectations are low based on past experience. Posting this is our main way to address it.

Similar to ASLR, forward-edge type-based CFI exists to make exploiting memory corruption vulnerabilities harder in the general case. It protects specific data (function pointers and virtual function tables) from attacks and only outright blocks attacks in a small subset of cases.

Clang CFI is least powerful in the Linux kernel and browser engine due to major holes in what it protects and many alternatives to function pointers for taking over control. Unfortunately, those are 2 of the places in the most need of much better exploit protections.

Android initially deployed CFI in the media stack and that's still where they focus on it. It was then added for the whole kernel. They're gradually expanding it in userspace starting in higher impact areas. We don't see much value in us focusing on gradually bringing it to lower impact areas.

Turning CFI from a weak or mediocre protection largely acting as an annoyance for attackers into a strong protection would require additional compiler features and a massive overhaul to software. There are too many holes in these protections and other exploit targets. It's ultimately a dead end.

Rather than making enormous changes to protect or remove exploit targets bit by bit, we need a strong general purpose protection. Memory tagging provides that, with the major caveat that MTE is only 4 bits. A future version can be given the bits from PAC. A far future one can use fat pointers.

Memory tagging with fat pointers will be usable to bolt on low overhead memory safety to massive legacy software stacks and to protect against remaining holes in memory safe languages. It's too bad there's so much focus on piling on more and more weak mitigations instead of building solutions.


This post is also available on social media platforms:

https://grapheneos.social/@GrapheneOS/113839722323674532
https://bsky.app/profile/grapheneos.org/post/3lfuzvysnrk2z
https://x.com/GrapheneOS/status/1879974709552406632

    GrapheneOS

    The post has been extended with significantly more information. If you read the older version, the new part starts here:

    Similar to ASLR, forward-edge type-based CFI exists to [...]

    Thanks for your ongoing hard work to protect users from vulnerabilities. Many people do not unserstand the brutality of real hackers and the importance of reducing attack surface or making the surface harder to penetrate.

    I'm so glad that anybody can download and install this class leading secure (and non corporate) OS into their pixel device for free. I would urge all appreciative users to make a one-off or monthly donation to support the expert work of the developers without whom this would not be possible.

    13 days later

    theauthors The methodology and the results are NOT valid. You're ignoring nearly everything we wrote above. GrapheneOS has Clang CFI deployed exactly where the stock OS does and doesn't reduce coverage as claimed in the paper. You're incorrectly counting the binaries and not taking into account that the way builds were done on 4th/5th generation Pixels results in redundant copies of them. The claim that we are adding a bunch of binaries is false. The claim that we were reusing the vast majority of the binaries from the stock OS is false. The claim that we were not greatly expanding CFI coverage despite enabling it in Vanadium (Chromium) for the browser and WebView is false. Chromium's codebase is massive. You don't count it because it's all inside a single APK and you're counting files with CFI instead of amount of code with CFI. You're also partially basing it on legacy extended support devices which are not official GrapheneOS releases.

    In case you are still convinced that the paper is flawed

    It is clearly flawed and you have not addressed the vast majority of what we wrote above. The only thing you've responded about is the lack of coverage for PAC/BTI, which is not the bulk of the issues with it.

    In case you are still convinced that the paper is flawed, please send a formal complaint request to ACM here:

    https://www.acm.org/publications/policies/publications-violation

    It's very strange for you to ignore nearly everything we've written and request that we file a formal complaint. Why can't you acknowledge what we've written and address it? The issues we've raised are valid.