GrapheneOS / hardened_malloc

Hardened allocator designed for modern systems. It has integration into Android's Bionic libc and can be used externally with musl and glibc as a dynamic library for use on other Linux-based platforms. It will gain more portability / integration over time.
https://grapheneos.org/
MIT License
1.26k stars 96 forks source link

Double-free result in hang on android #234

Closed jvoisin closed 9 months ago

jvoisin commented 9 months ago

I was playing with com.sanitizers.app.production, and got the following results:

thestinger commented 9 months ago

heap out-of-bound read: not caught by anything

There's size class rounding. It's probably not reading far enough past the end. Bear in mind there are still canaries enabled with MTE at the moment due to how it can be disabled at runtime.

double-free: hang indefinitely, every time.

It's a bug in the crash handling of the app.

thestinger commented 9 months ago

java-crash: hang, then silently crash

Android doesn't report the first crash. We have our own crash reporting for MTE crashes.

eugenis commented 9 months ago

We have our own crash reporting for MTE crashes.

I'm curious - do you have any pointers about that?

thestinger commented 9 months ago

We have user-facing crash reporting creating a notification after a kernel crash, system_server crash and certain other kinds of crashes including MTE.

GrapheneOS always enables MTE and always uses it for the whole base OS other than prebuilt vendor executables and currently a special exception for surfaceflinger due to new upstream bugs in Android 14 QPR1.

We enable MTE by default for user installed app processes which explicitly opt-in to MTE and apps without any native libraries. It's only enabled for their native processes if they build them with MTE. We provide a user-facing toggle in Settings -> Security for enabling MTE for other user installed apps along with a per-app toggle. The notification about an MTE crash explains the per-app toggle in case it's an app bug preventing using the app rather than a rare crash. Users can't disable it for the base OS and apps that are supposed to be compatible with it.

You would need to look in https://github.com/GrapheneOS/platform_frameworks_base/, https://github.com/GrapheneOS/platform_packages_apps_Settings, etc. If you have a Pixel 8 or Pixel 8 Pro, it's very easy to install GrapheneOS with https://grapheneos.org/install/web to see what we provide for this.

thestinger commented 9 months ago

For normal Java crashes, Android only shows a crash report after the first crash. We tried showing a report after the first crash but there are too many app bugs and people started flooding us with reports from third party app bugs unrelated to GrapheneOS. Most of the issues people report right now are upstream bugs but in some cases we need to do something about it.

thestinger commented 9 months ago

We use hardened_malloc by default, but there's a per-app toggle to disable it which results in using the default of Scudo. hardened_malloc is 64-bit-only so Scudo is also used for 32-bit, but the Pixel 7 and later dropped 32-bit app support and the Pixel 8 has no 32-bit hardware support at all. Pixel 7 still has 32-bit support built and just doesn't support a 32-bit zygote to spawn apps.

There's also a per-app toggle for the extended address space we use by default on 64-bit, which hardened_malloc requires. Extended address space will make PAC much less useful but we don't see much point in PAC when MTE can provide deterministic return address protection and more.

There's also a per-app toggle for native debugging (ptrace) for kernel attack surface reduction, but for usability it's enabled by default. If users disable native debugging, they get a notification when an app tries to use it. There's a global toggle for this too, so the intention is that advanced users can disable it globally, then enable it for apps requiring it.

On Pixel 8 and Pixel 8 Pro, there's also the global and per-app memory tagging toggle for force-enabling it for user installed apps which may be incompatible.

For base OS apps, the security features are force enabled and can't be turned off with these, at least in user builds.

Our per-app exploit protection compatibility mode disables hardened_malloc, extended address space, memory tagging and enables native debugging.

In very rare cases, apps check the call stack and refuse to run with exec-based spawning. This shouldn't be an issue and is frustrating. We don't want to provide a per-app toggle for this feature because it doesn't make sense. We could potentially mimic the standard call stack to deal with it. Should not be an issue, but apps are stupid. Many are moving to the Play Integrity API to explicitly disallow using a non-Google-certified OS which is very frustrating and we believe this is likely illegal within the EU under current laws but we lack resources to pursue that and don't want to make an enemy out of Google rather than collaborating with them despite the fact that they're hindering us in so many ways like this. It's currently easy to spoof the Play Integrity checks for the basic software mode but it requires pretending to be a device without working hardware attestation which will eventually not be supported anymore, and they are actively blacklisting the build fingerprints that are being used at scale for this. It's quite annoying since their approach prevents an OS like GrapheneOS from working around it but doesn't provide any real security value. It's easy to bypass but not for something shipped to 200k users with releases every week or two. Most of these exec-based spawning incompatibilities will stop mattering since apps will move to just outright forbidding a non-Google-certified OS in addition to their existing misguided, incredibly insecure anti-tampering checks. It's unfortunate so many apps have security theater like this which accomplishes nothing and hinders people using a more private and secure OS. It's a joke that they allow an OS with a security patch level from 2021 but not GrapheneOS because it isn't Google certified.

thestinger commented 9 months ago

Made some edits to the last comment.

jvoisin commented 9 months ago

This was worked around by 365ee6900d2ae0cc9ad9e03d48f6747f58deb69d