Research · android · privilege-boundary · responsible-disclosure

When a media preview reaches a privileged process

A preview should only look. On a Galaxy S22 Ultra, Samsung's SoundPicker can generate a ringtone "highlight" from an ordinary audio file — and that work runs a native FLAC decoder inside a privileged system process, not inside the app that supplied the file. The decoder sat on a memory-safety bug class Samsung already fixed as CVE-2026-21042 / SVE-2026-0716. The finding we reported is the crossing: an unprivileged input reaching privileged native code through a low-interaction path, independent of that one bug. Reported to Samsung under coordinated disclosure. This is exploit research about a boundary, written to be verifiable without becoming a recipe — no malformed-file parameters, heap-grooming sequences, or reproducer appear here.

The preview that is not passive

A preview is easy to dismiss because it looks passive. But nothing about producing one is passive: some component still has to open the file, parse the container, decode the stream, allocate native objects and interpret metadata. If that pipeline runs inside a privileged process, the preview becomes part of the privileged attack surface.

On Samsung devices the ringtone-selection flow does more than display metadata. SoundPicker can invoke a native audio-analysis pipeline to compute a short "highlight" from an ordinary media file. We traced where that work actually executes.

The reachability chain
  1. Untrusted media file (MediaStore)
  2. Samsung SoundPicker
  3. AudioThumbnailCompat.extractHighlight()
  4. SemAudioThumbnail.extract()
  5. JNI boundary
  6. libsmat.so — native media stack
  7. FLAC decode — runs as platform_app

Threat model

The starting condition is deliberately ordinary. Any untrusted source — a downloaded file, a messaging app, a sync service, a browser download — can make an audio file available through Android’s media infrastructure. Nothing about the file grants privilege.

A parser bug inside an isolated media sandbox and the same bug inside a privileged platform process are not the same security event. The parser may be identical; the security context is not. That transition — from an application-UID source to a platform_app process — is what we set out to characterize.

Test device
DeviceSamsung Galaxy S22 Ultra
ModelSM-S908U
SoCSnapdragon SM8450
Android16
BuildS908USQSAGZF3
Security patch2026-06-05
Verified Bootlocked / green
Knox warranty bit0

Mapping the privileged surface

The first step is not exploitation, it is surface mapping. For a system app that consumes user-controlled files, the questions that matter are: which app receives the content, which components are exported, which process performs the parsing, which UID owns that process, which SELinux domain contains it, and whether parsing happens before explicit user interaction.

On the test device the answer that mattered was that the highlight feature eventually enters Samsung’s native audio-analysis implementation, and that this runs inside SoundPicker itself — a platform_app process (observed UID 10236), not a generic isolated media extractor.

Surface mapping

Read-only inspection of a shipping device. Nothing here parses a malicious file.

# what the package exports and who can reach it$ adb shell dumpsys package com.samsung.android.app.soundpicker# which UID and SELinux domain own the process$ adb shell ps -AZ | grep soundpicker

Following Java into native

Exported-component review alone is not enough: the exported activity is only the entrance. The interesting question is what privileged native code becomes reachable after that entrance. We treat JNI boundaries as security boundaries worth mapping explicitly — decompiling the app, finding the vendor media APIs it calls, and correlating those Java native methods with the exports of the native library behind them.

Real on-device crash backtraces confirmed that SemAudioThumbnail enters Samsung’s media stack through JNI into libsmat.so, and that the owning process on the crash was SoundPicker, not a sandboxed extractor.

Correlating the JNI boundary

# decompile and search for the vendor media API$ jadx -d out SoundPicker.apk$ rg -n "SemAudioThumbnail|extractHighlight" out/# match the Java native method to a library export$ nm -D libsmat.so | grep -i thumbnail

Root cause: the decoder bug behind the boundary

The native FLAC decoder on the tested firmware was affected by the memory-safety issue Samsung later addressed as CVE-2026-21042 / SVE-2026-0716. In simplified terms, the LPC (linear predictive coding) subframe decoder writes one warm-up sample per prediction order into a per-channel buffer that was sized for the block size.

The vulnerable shape (simplified)

allocate_channel_buffer(block_size);

for (i = 0; i < lpc_order; i++)
    channel_buffer[i] = read_warmup_sample();

When the order exceeds the block

The overflow condition is simply lpc_order > block_size: the allocation is sized for the block, while the loop writes according to the prediction order. The fixed decoder rejects that relationship before performing the writes. Binary comparison of the pre- and post-fix library showed a small validation patch around exactly that condition.

What the fix enforces

if (lpc_order > block_size)
    return ERROR;

if (lpc_order > FLAC_MAX_LPC_ORDER)
    return ERROR;

Patch diffing the invariant

Once a vendor ships a fix, binary diffing is one of the most useful ways to recover the security invariant that changed. The goal is not "these binaries differ" — it is "what input assumption did the vendor decide must now be enforced?" Here, the answer was the relationship between LPC order, block size and the FLAC maximum order.

Recovering the invariant from public firmware

# identify the two library versions$ sha256sum old/libsavsac.so new/libsavsac.so# compare exported symbols, then diff in a disassembler$ readelf -Ws old/libsavsac.so > old.sym; diff -u old.sym new.sym

The exploitation boundary

A generic heap crash is weak evidence, so the real question is always whether the attacker influences what is written, or only where the allocator later notices damage. Using an instrumented, throwaway userspace copy of the decoder — the system library was never replaced — we confirmed the warm-up writes carry per-word attacker influence, and we then reproduced the corruption inside SoundPicker itself, where Android’s Scudo allocator aborted on a damaged chunk. Under some heap layouts a corrupted neighboring object led to a constrained, target-dependent influence over native control flow.

That is where we stopped, and we are precise about it. The malformed-file construction, the heap-layout and grooming work, and the reproducer are deliberately omitted while disclosure is open. What matters for this article is the boundary the primitives establish, not the primitives as a recipe.

What we demonstrated, and what we did not

Demonstrated

  • Vulnerable FLAC path identified and reached
  • Vulnerable vs fixed decoder isolated by binary diff
  • Out-of-bounds native heap write reproduced, with per-word influence
  • Corruption reproduced inside Samsung SoundPicker (platform_app)
  • The privilege boundary from untrusted input confirmed
  • A constrained, target-dependent control-flow influence observed

Not claimed

  • Arbitrary address/value write
  • Reliable arbitrary PC control
  • Arbitrary native code execution
  • Sandbox escape beyond SoundPicker
  • Root
  • Persistent compromise

Why SoundPicker privilege matters without root

Even full code execution inside SoundPicker would not imply UID 0. SoundPicker runs as a platform application, holding privileges such as WRITE_SECURE_SETTINGS, MANAGE_USERS and INTERACT_ACROSS_USERS — meaningful, but not root. An exploit chain would still have to distinguish code execution in SoundPicker from root; those are separate stages.

The reason SoundPicker remains security-sensitive is not that it equals root. It is that reaching it at all is a privilege transition away from the untrusted source that supplied the file.

A rule for reviewing previews
  1. Input trust
  2. Who parses it?
  3. In which process?
  4. With which privileges?
  5. Before which user action?

Disclosure

We reported the privileged SoundPicker preview reachability to Samsung Mobile Security under coordinated disclosure, alongside a second, distinct hardening issue in a neighboring native component reachable from the same path. Samsung's initial assessment associated the underlying decoder behavior with the already-fixed CVE-2026-21042 / SVE-2026-0716.

Our position is narrower and architectural: the fixed decoder vulnerability and the existence of a low-interaction path from untrusted media into privileged native decoding are separate security questions. While the reachability discussion stays open, we are withholding the malformed-file parameters, exploit-oriented heap layouts, grooming sequences, trigger files and reproducer. The public material is intentionally enough to explain and validate the finding without becoming an exploitation recipe.

A scanner can flag a vulnerable library. The work begins when you show who can reach it, in which process, with which privileges, and what boundary failed when the input arrived. That boundary is the finding — and naming exactly where you stopped is what keeps it honest.

More research

Shall we put this to the test?

We define the scope with you and start with written authorisation.

Request an assessment
KNULL / DATA
DATA / CONTACT

Only what
we need.

This page collects nothing. The request form on the home page stores only what you send it, on the server that hosts this site, with no analytics and no AI model.