Skip to content

CrashUAF_ObtainReleaseBuffer

Phil Burk edited this page Mar 29, 2023 · 2 revisions

In March 2023 we discovered a bug in AudioTrack, b/274815060, that was introduced in 2012.

It can cause an intermittent crash in a data callback due to accessing memory after it has been freed.

See #1763

Signature

This crash has the following characteristics:

  • Legacy stream, not MMAP
  • crash happens before stream is closed
  • audio routing changed between devices that run on different HALs, eg. Bluetooth to speaker
  • Full bugreport log probably has: "AudioTrack: restoreTrack_l(*): dead IAudioTrack"
  • Crash stack trace contains: "AudioTrack::processAudioBuffer()"

Workarounds

There are things you can do that will greatly reduce the probability of the crash.

  1. Do not call stream->getFramesRead() from inside the callback of an OUTPUT stream.
  2. Do not call stream->getFramesWritten() from inside the callback of an INPUT stream.
  3. Do not call stream->getTimestamp() from inside the callback of any stream.
  4. Reduce the CPU load inside your callback.

Root Cause

AudioTrack uses shared pointers to protect the allocated buffer. But it returns a raw pointer from obtainBuffer() and then passes that to the callback handler. The app callback then writes to the buffer using that raw pointer.

Unfortunately, a rerouting can occur shortly after obtainBuffer() is called. That can free the buffer that the callback is using. Then when the callback tries to write the buffer it gets a segfault and crashes. This has been fixed by holding an extra shared pointer between obtainBuffer and releaseBuffer.

This bug is in the same part of the code as TechNote_ReleaseBuffer.