deckerst / aves

Aves is a gallery and metadata explorer app, built for Android with Flutter.
BSD 3-Clause "New" or "Revised" License
2.48k stars 93 forks source link

Hardened malloc / Shaders / Crash caused by memory corruption bug uncovered by GrapheneOS's hardened memory allocator #398

Closed rowboatz closed 1 year ago

rowboatz commented 1 year ago

Describe the bug On GrapheneOS, when hardened_malloc is used (as is the case by default), after exiting Aves using Android's "back" function specifically, opening it again leads to an instant crash.

To Reproduce

  1. Use GrapheneOS in its default configuration
  2. Open Aves
  3. close it using the "back" function
  4. try opening it again
  5. Aves crashes

Expected behavior Aves shouldn't crash, even when all GrapheneOS security features are enabled.

System information and logs: Aves version: 1.7.4-izzy (Build 2084) Flutter version: 3.3.8 (Channel stable) Android version: 13 (SDK 33) Android build: TP1A.221105.002.2022111000 Device: Google Pixel 6 Geocoder: not available Mobile services: ready System locales: fr_FR Aves locale: system -> fr Installer: com.android.packageinstaller aves-logs-20221112_141051.txt

Additional context Enabling GrapheneOS's "exploit protection compatibility mode" (which reverts to Android's standard adress space size and memory allocator (instead of hardened_malloc)) for Aves keeps it from crashing, however this crash still points to an issue in Aves, not GrapheneOS or hardened_malloc. Aves is the first app, out of all the ones I've used, that has such an issue. Tried a bunch of other gallery apps and none of them misbehaved like this, for example. I can help if you need me to try some test builds. Maybe having a look at GrapheneOS and hardened_malloc's documentation could help you: https://grapheneos.org/usage#bugs-uncovered-by-security-features https://github.com/GrapheneOS/hardened_malloc

deckerst commented 1 year ago

I'll take a closer look, but i will indeed probably need you to test builds, because i don't have the setup to test this myself.

Do other Flutter apps have the issue? For example, BlackHole or Spotube (i haven't tried these apps but they seem to be famous flutter open source apps).

rowboatz commented 1 year ago

Do other Flutter apps have the issue? For example, BlackHole or Spotube

Just tried these ones and multiple other Flutter apps, the only one I found which crashed in similar circumstances is SpaceX GO!. Here is its source code. The only difference being that I have to clear its app data after each crash to be able to reproduce it consistently. If I don't clear its app data, it crashes once after first launch and then inconsistently. Aside from that, it seems to behave in the exact same way:

I could try to find more Flutter apps to reproduce it later, if it can help you. In the mean time, would the logs from SpaceX GO! be useful?

edit: in any case, here's a crash log from SpaceX GO!. hardened_malloc reports the following: "fatal allocator error: detected write after free" as it does with Aves. Not sure to what extent this could help identify the problem. SpaceX GO! crash.txt

deckerst commented 1 year ago

I hadn't noticed in your report using Android's "back" function specifically. If you kill it instead by wiping it from the recent apps, it doesn't crash when you reopen it? And please let me know any other way to leave/reopen the app (and whether they crash or not).

If you don't mind, could you try this old release Aves v1.5.11. And if v1.5.11 works, trying the next one Aves v1.6.1?

rowboatz commented 1 year ago

If you kill it instead by wiping it from the recent apps, it doesn't crash when you reopen it?

That's right. When Aves is running and in focus:

So basically, it seems to crash exclusively when trying to open after having been closed with the Back button/gesture.

rowboatz commented 1 year ago

If you don't mind, could you try this old release Aves v1.5.11. And if v1.5.11 works, trying the next one Aves v1.6.1?

I found something curious. I originally installed the latest v8a build of Aves, which crashed. The v8a builds of 1.5.11 and 1.6.1 that you suggested crash in the same manner. However, none of the v7a ones crash, no matter what version of the app.

To make things more complex, GrapheneOS doesn't show the 'compatibility mode' toggle in settings for v7a builds so I don't even have a way to know why exactly they're not crashing. It could be the fact that they're 32bit or the fact that GrapheneOS doesn't apply security hardening in the same manner. I'll try to find some information on that.

So, for the time being only v8a apks are confirmed to be problematic. Regardless, they still shouldn't be crashing in the way I originally reported, I'm pretty sure.

edit: I have confirmation that, on GrapheneOS, hardened_malloc is never used for 32bit apps, so the memory corruption issue is most likely also present in 32bit builds of Aves, it just doesn't lead to a crash since the default memory allocator isn't as strict. This also means that I would need 64bit test builds to help solve this issue, since with 32bit builds this bug flies under the radar.

SigmaBonder commented 1 year ago

I can also confirm this bug on Pixel 7 Pro. I've noticed it while trying some things, but didn't investigate enough to come up with reproducible scenario.

deckerst commented 1 year ago

I don't see any obvious culprit among the plugins I'm using, and I don't think Aves does anything special when exiting (especially not with v1.5.11). It's hard to know what's causing this issue, and it feels unpractical to submit a plethora of various builds for you to try.

I was tempted to try GrapheneOS on a spare device I have (a Galaxy S7) but it seems GrapheneOS is only for Pixel devices? Is there any rom with this hardened malloc feature that would be available for an old Samsung device?

SigmaBonder commented 1 year ago

Yup, GrapheneOS is Pixel-exclusive. I'm not aware of any other OS that would copy Graphene's improvements in this regard and support a device like yours. I can offer my help in testing various variants, though.

deckerst commented 1 year ago

Ok, thanks for the info.

If you want to help (but really, it will be time-consuming), you can try ancient builds, getting the APK from the release page, starting with the oldest (v1.0.9).

If it works fine, then go by dichotomy between v1.0.9 and v1.5.11 to find in which release the issue emerged. Even if you can't pinpoint the exact threshold release, any pass/fail result is useful.

If even Aves v1.0.9 fails, I'll try and think of another strategy.

rowboatz commented 1 year ago

I just tested a couple dozen builds and it turns out the crash starts occuring with 1.1.4. 1.1.2 doesn't crash. Haven't tested all the older builds but it's pretty solid evidence that that's where it was the problem was introduced.

SigmaBonder commented 1 year ago

Done. I haven't tested all of the versions between 1.0.9 and 1.1.2, but: 1.1.2 doesn't crash, 1.1.4 does.

Oh, @rowboatz, you were faster. But now we have two confirmations. :-)

Somewhere later the "tap back again to exit" was introduced, and I initially thought these two things might be linked, but 1.1.4 doesn't have this feature yet.

deckerst commented 1 year ago

Good. I'll try and make a few v1.1.2 / v1.1.4 builds with variants.

deckerst commented 1 year ago

Could you please try these? 1) aves-play-release_20221113_1900_with_shaders 2) aves-play-release_20221113_1900_no_shaders

Fairly recent builds, but the difference is in the bundling of pre-compiled shaders, which is one of the major differences between v1.1.2 and v1.1.4.

SigmaBonder commented 1 year ago

First version crashes, the second doesn't.

deckerst commented 1 year ago

So the good news is that I don't have to investigate further, but the bad news is that these shaders are not behavioral code from me. They are generated from a test scenario run on a real device, then bundled when compiling the release artifacts. They are useful to avoid stuttering during the compilation of shaders when launching the app for the first time. The choice is here is either:

To bundle, or not bundle... that is the question :/

SigmaBonder commented 1 year ago

Can't you change the UI on first launch somehow in order to not need the precompiled shaders? Disable animations or something?

deckerst commented 1 year ago

Can't do that. But what I'll do is to bundle shaders for the play/huawei versions, and not bundle them for the izzy/libre versions. I expect shaders to not be necessary in the long run (Flutter currently works on a new rendering runtime supposed to solve the early jank problem), and in the meantime it will allow foss folks to enjoy their additional privacy features. Sounds good?

SigmaBonder commented 1 year ago

Sounds perfect, I don't expect anyone running GrapheneOS to use any other version (even though they technically could).

deckerst commented 1 year ago

Aves v1.7.5 is available via IzzyOnDroid. Does it work well for you?

rowboatz commented 1 year ago

The latest release works fine! Ideally the issue would be resolved across the board however I understand that, for the time being, you have to make compromises and this one is decent enough IMO. Thank you and great work, Aves is a very nice app!

Related: the IzzyOnDroid repo seems to only serves the v7a builds, do you know why that is? I don't find it bothersome since I tend to update apps directly from GitHub but, if you don't also release v8a builds over there, it might be a good idea to do so considering the fact that Android is moving towards 64-bit only (latest Pixels for example only support 64-bit apps). Not sure if this should be discussed elsewhere, if so, just tell me.

deckerst commented 1 year ago

The reason only the v7 build is available via Izzy is because Izzy's repo has a policy to not accept APKs over 30MB or so. Aves "fat" APK is over that limit, so the compromise here is to split the APK by ABI and distribute the one for the most common ABI, which is v7. That said, the APK for v8 is also available via GitHub (as you know), and you could use something like Obtainium, for updates.