Closed Bug 1668674 Opened 2 years ago Closed 2 years ago

Tab crash: uninitialized allocator usage

Categories

(Core :: Memory Allocator, defect)

78 Branch
defect

Tracking

()

RESOLVED INVALID

People

(Reporter: cyanlemons, Unassigned)

Details

User Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0

Steps to reproduce:

  1. Use the hardened_malloc allocator when running FireFox: https://github.com/GrapheneOS/hardened_malloc
  2. Disable any blockers such as uBlock Origin/AdBlock.
  3. Visit the following page: https://stackoverflow.com/questions/8981164/self-deleting-shell-script
  4. Scroll up and down a bit, and wait a moment.

Actual results:

"Gah. Your tab just crashed."

When running FireFox with verbose outputs, the following is printed in my terminal right as the tab crashes:
fatal allocator error: invalid uninitialized allocator usage
Redirecting call to abort() to mozalloc_abort

No other relevant information is printed.

Although it is technically possible that this is an issue with the allocator, based upon the circumstances and the specific error at hand, I am relatively confident this is simply a memory safety bug in FireFox.

Expected results:

The tab should not have crashed.

It may be worth noting that my Firefox about:config has been hardened, with the typical fingerprinting resistance options enabled, along with a few others.

Relevant comment from Daniel Micay:

I don't think there's much chance that this is a hardened_malloc bug, but it's probably not simply a memory corruption bug in Firefox. It's some kind of more complex issue like Firefox attempting to mix different malloc implementations such as by not completely replacing all of the symbols. It sounds like the issue occurs after early initialization (although maybe this happens in a freshly spawned process) so that makes it seem like hardened_malloc is not really being used until some point where it ends up calling into a function like malloc_usable_size that passes through to hardened_malloc instead of their incomplete overrides of the symbols. I'm not really sure what's happening.

I have recompiled hardened_malloc with a log before every enforce_init() call to figure out what was called before this error occurs. Here is what I have discovered:

  • The error at hand should only ever occur when hardened_malloc is used before any initialization has occurred. For instance, attempting to deallocate memory before ever doing a single allocation would trigger this error.
  • The crash occurs immediately after deallocate_large() is called. This means there was an attempt to free memory before hardened_malloc was initialized. This may be due to an incomplete replacement of malloc symbols, or it could simply be the case that some new Firefox process was trying to free before it ever allocated any memory.
  • Throughout normal browsing, both deallocate_large() and h_realloc() are regularly called without any crashes, and both of these functions verify that the allocator has been initialized. For h_realloc(), this initialization verification only occurs in a specific else branch, not on every call.
  • This crash can only be reproduced with ad blockers turned off. Furthermore, it seems the tab crashes right after the Google Ad on Stack Overflow loads.

Terminal output including my custom hardened_malloc debug logs:

deallocate_large(): calling enforce_init()
fatal allocator error: invalid uninitialized allocator usage
Redirecting call to abort() to mozalloc_abort

Assigning "Core: Memory Allocator" component.

Component: Untriaged → Memory Allocator
Product: Firefox → Core

You can't use an alternative allocator via LD_PRELOAD without rebuilding Firefox with --disable-jemalloc.

Status: UNCONFIRMED → RESOLVED
Closed: 2 years ago
Resolution: --- → INVALID

Is there any particular reason this is unsupported? Rebuilding FireFox every time a new version is released isn't exactly practical. As glibc explicitly supports loading an alternative allocator via LD_PRELOAD, I see no reason why it couldn't work with FireFox.

It just doesn't work because of how LD_PRELOAD works (it doesn't take precedence over symbols provided by the executable) combined with the fact that jemalloc is in the Firefox executable.

You need to log in before you can comment on or make changes to this bug.