Skip to content

fastrpc: DSP-supplied buffer lengths are not validated before the sbuf cursor advances (SIGSEGV; CVE-2020-11206 pattern still present) #392

Description

@angelwzr

FastRPC version

1bd8835 (vulnerable code is byte-identical on current development HEAD d247519)

DSP firmware version

ADSP.VT.5.4-00283-NICOBAR_1.0 (build 2019-09-04; strings dspso.bin, stock V12.0.26.0 vendor image)

SoC and device name

Qualcomm SM6125 (Snapdragon 665) — Xiaomi Mi A3 (laurel_sprout), running mainline Linux (NixOS)

Kernel version

7.3.0-rc1 (mainline)

What happened?

The ADSP default listener (adsprpcd audiopd) died with SIGSEGV in
__memcpy_generic called from listener() (libadsprpc.so+0x32c1c).
Forensics on the retained core: si_addr = input_buffer_base + 0xc8e8e6e7
against a 4 KiB input buffer; the last decoded length word on the stack was
0x6474735f (~1.57 GiB).

Root cause, reproduced on host and on the device itself with a minimal
gate that drives the real unpack_in_bufs():

  1. unpack_in_bufs() (inc/listener_buf.h) advances the sbuf cursor by a
    DSP-supplied 4-byte length without validating it. pra[].buf.pv is
    only assigned when the original (int)len <= sbuf_left(buf) comparison
    happens to hold; on mismatch pv is left stale/NULL while the cursor
    still escapes the buffer.
  2. sbuf_left() (inc/sbuf.h) subtracts two uintptr_t into an int.
    With the escaped cursor the true remainder is -3370702567, which
    overflows int32 and wraps to +924264729, so the caller's bounds check
    passes and sbuf_read()'s memmove dereferences the wild cursor.

Gate results (lengths: 0x6474735f, remaining+1, 0x7fffffff, 0x80000000,
0xffffffff):

headers result
original, host x86-64 SIGSEGV
original, device aarch64 (this phone) SIGSEGV
AOSP android-17.0.0_r1, host SIGSEGV
patched (see linked PR), device aarch64 all contained, exit 0

This is the CVE-2020-11206 pattern ("buffer overflow in Fastrpc while
handling received parameters due to lack of validation on input
parameters"); SM6125 is in the affected list. The November 2020 fix shipped
only as a closed-source component, so this open-source tree never received
it — the identical unchecked pattern is still present on development HEAD
and in AOSP platform/external/fastrpc through android-17.0.0_r1.

Patch proposal linked: validates the length in unsigned arithmetic against
the true unsigned remainder before the cursor advances, and computes
sbuf_left unsigned with clamping. Patched fastrpc userspace has been
running on the device as the live audiopd listener since deployment:
Type=notify readiness reached, no SEGV, normal operation.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions