# Zero-Permission Android Apps Can Chain AtlasService and olc2 to Gain Root on OnePlus/OPPO Devices via OxygenOS Confused-Deputy Flaws

> Independent researcher Rasmus Moorats disclosed a two-stage privilege-escalation chain in OnePlus's OxygenOS: a root-privileged debugging service, AtlasService, accepts unauthenticated Binder calls and injects attacker-controlled input into a shell command via the audioDumpInfo binary, and a vendor hardware-abstraction service, olc2, then executes arbitrary shell commands for any caller already running as root. Chained, the two bugs let an installed Android app that declares zero permissions achieve full root with kernel-module-loading capability on a stock OnePlus 15 (and a OnePlus 12 Pro), a class OnePlus confirmed on 2026-05-20 affects "all series of OPPO terminal products" but has neither assigned a CVE nor shipped a confirmed public fix as of the 2026-09-24/25 disclosure.

- **Published:** 2026-09-27T00:00:00Z
- **Last reviewed:** 2026-09-27T00:00:00Z
- **Canonical:** https://intel.threadlinqs.com/threat/TL-2026-2683
- **Card image:** https://intel.threadlinqs.com/og/threat/threat-intel-oneplus-zero-permission-root-chain-tl-2026-2683.webp?v=7ebf391c (Threadlinqs threat intel: OnePlus Zero-Permission Root: Detection & IOCs (TL-2026-2683) — High severity, 11 IOCs, 9 detection rules.)
- **ID:** TL-2026-2683
- **Severity:** HIGH
- **Category:** VULNERABILITY
- **Status:** ACTIVE
- **Detections:** 9 (1 shown free below) · **IOCs:** 11

## Description

On 2026-09-24, security researcher Rasmus Moorats published a technical writeup (blog.nns.ee) of a two-bug exploit chain that escalates an unprivileged, zero-permission Android application to full root on OnePlus's OxygenOS, later syndicated by The Hacker News, Cyber Security News, and other outlets.

The first bug lives in AtlasService (`atlasservice`), a OnePlus telemetry/debugging system service that runs as root and accepts Binder calls without verifying the caller's identity. The service exposes a `setEvent(String8 name, String8 value)` method at Binder transaction code 2, handled internally by `OplusAtlasLogWriter::handleEvent`. When an app supplies the event name `atlas_event_multimedia_audio_dumpsys`, AtlasService calls `property_set("oplus.audio.dumpinfo.type", value)` with the attacker-controlled value and triggers `ctl.start=audiodumpinfo`. Per the service's init definition at `/system_ext/etc/init/audiodumpinfo.rc` (`user root`, `group root system everybody sdcard_rw`, `seclabel u:r:dumpstate:s0`, `oneshot`), this starts `/system_ext/bin/audioDumpInfo` as UID 0 in the `dumpstate` SELinux domain. That binary reads the attacker-controlled property and passes it, unescaped, into a `system()` shell call — a classic command-injection sink reachable with no Android permissions at all. The researcher's proof-of-concept injected the property value `x;sh</sdcard/Android/data/com.research.poc/files/boot.sh 2>&1|log -t AtlasOut;#`, using a shell metacharacter break-out to execute an attacker-supplied script staged in the app's own external files directory. This yields code execution as UID 0, but confined to the restricted `dumpstate` SELinux domain.

The second bug is in `olc2` (`vendor.oplus.hardware.olc2.IOplusLogCore/default`, backed by the binary `/odm/bin/hw/vendor.oplus.hardware.olc2-V3-service`), a vendor hardware-abstraction-layer (HAL) service meant to support hardware logging/diagnostics. Its `doShell(String cmd)` method (Binder transaction code 6) contains only a single check — `if (getCallingUid() == 0)` — before it forks and calls `execl("/vendor/bin/sh", "sh", "-c", cmd, NULL)`. Because the caller is already root (courtesy of the first bug), this check is trivially satisfied — a textbook confused-deputy failure where a privileged service trusts a caller's claimed UID instead of cryptographically verifying it. The researcher additionally located a permissive SELinux policy rule (`allow hal_oplus_olc_aidl_client hal_oplus_olc_aidl_server:binder { call transfer };`) that permits the `dumpstate`-domain process reached in stage one to make the Binder call into `olc2` at all — identified via `sesearch -A -s dumpstate -c binder sepolicy_clean.bin` against the device's compiled policy. Crucially, the shell spawned by `olc2` inherits the `vendor_qti_init_shell` SELinux domain, which carries an almost unrestricted capability bitmask (`CapBnd = 0x1ffffffffff`) including `CAP_SYS_MODULE` (kernel module loading) and `CAP_SYS_RAWIO` — a much less restricted context than `dumpstate`. Chaining the two bugs takes a zero-permission app from nothing to unrestricted root with kernel-level capability in two Binder calls.

Moorats reverse-engineered both services with Ghidra and documented that Java can call the vendor AIDL/HIDL HAL directly via `ServiceManager.getService()`, `Parcel.writeInterfaceToken()`, and `IBinder.transact()` — a pattern that "unexpectedly" worked without special HIDL bindings — and had to hand-implement the legacy `String8` wire format (int32 length + UTF-8 bytes + null terminator) for the `setEvent` call since the modern Android 35 Parcel API does not expose it. To execute arbitrary Java logic once root was reached, the researcher staged `classes.dex` from the PoC app's own APK to external (`media_rw_data_file`) storage at `/sdcard/Android/data/com.research.poc/files/classes.dex` — because `dumpstate` cannot read installed-APK data files directly — then launched it by setting `CLASSPATH` and invoking `app_process /system/bin com.research.poc.Pwn` from the `boot.sh` payload run inside the `olc2`-spawned root shell.

The vulnerability was confirmed on a OnePlus 15 (CPH2747) running OxygenOS 16.0.3.503 (February 2026 security patch level, kernel 6.12.23), and separately reproduced on an older OnePlus 12 Pro (CPH2581) used during reverse engineering, leading the researcher to expect the flaw is present across OxygenOS 16 generally. OnePlus's own Security Response Center told Moorats by email that the issue affects "all series of OPPO terminal products with universal security risks" — an admission of fleet-wide impact without naming specific additional models.

Disclosure did not go smoothly. Moorats reported both bugs on 2026-04-18 and followed up on 2026-04-29 after no reply; OnePlus requested further technical detail on 2026-05-14 (answered same day) and confirmed the bugs on 2026-05-20, simultaneously asserting "the exclusive final right of vulnerability disclosure" and warning that publication — even after a fix ships — could expose the researcher to "legal liabilities" under European cybersecurity regulation. On 2026-06-01 the researcher set a standard 90-day coordinated-disclosure deadline; OnePlus instead requested a delay to 2026-09-17 on 2026-06-22, which the researcher accepted. A 2026-07-20 status request went unanswered; the two sides exchanged messages regarding CVE-ID coordination around 2026-07-28, and OnePlus sent a further response on 2026-08-03, but no CVE identifier was ever publicly assigned. A final 2026-09-11 status request also went unanswered. Moorats published on 2026-09-24, roughly 159 days after the initial report and past the previously agreed embargo date. Reporting on the patch status is inconsistent across outlets: several outlets (Cyber Security News, The Hacker News, as of their 2026-09-24/25 publication) state no public patch or OTA is available, while the researcher's own writeup references OxygenOS build `16.0.10.500(EX01)` as containing a fix — it is unclear from public reporting whether that build has been broadly rolled out to the affected device fleet, particularly the OPPO-branded devices OnePlus itself says are impacted. No CVE has been assigned to this flaw as of 2026-09-27.

The disclosure lands amid a broader pattern of OEM-added-code privilege escalation on Android flagships: on 2026-08-31, independent researcher Lukas Maar (Calif) published "OEMpocalypse," a distinct zero-permission-to-root technique exploiting a page use-after-free in OEM-specific kernel drivers, demonstrated against locked-bootloader Samsung Galaxy S26/S26 Ultra, Xiaomi 17, OPPO Find X9 Ultra, and OnePlus Ace 6 Ultra devices. OEMpocalypse is a separate bug class (kernel memory corruption vs. this chain's userspace confused-deputy/command-injection pair) but underscores the same underlying theme reporters connected it to: manufacturer-added system code on Android flagships, not upstream AOSP or chipset-vendor drivers, is an increasingly common root of unprivileged privilege-escalation chains.

No real-world exploitation of the AtlasService/olc2 chain has been reported. Exploitation requires local app installation (e.g., sideloading or an app obtained outside vetted stores) but no Android runtime permissions and no user interaction beyond installing the app; impact at the end of the chain is full root with unrestricted Linux capabilities, meaning arbitrary access to other apps' data, the ability to install persistent code, tamper with or disable on-device security tooling, and load kernel modules.

## MITRE ATT&CK

- T1575 Native API
- T1623 Command and Scripting Interpreter
- T1623.001 Command and Scripting Interpreter: Unix Shell
- T1404 Exploitation for Privilege Escalation
- T1625.001 System Runtime API Hijacking
- T1629 Impair Defenses
- T1629.003 Impair Defenses: Disable or Modify Tools
- T1424 Process Discovery
- T1418 Software Discovery
- T1409 Stored Application Data

## Free detection (Splunk SPL, Microsoft KQL, Sigma)

**SPL: OxygenOS AtlasService Confused-Deputy Property Injection → audioDumpInfo Command Injection** (`TL-2026-2683-SPL-001`)

Detects the stage-one exploit: a zero-permission app invokes AtlasService's setEvent(name='atlas_event_multimedia_audio_dumpsys', value) Binder method (transaction code 2), driving property_set('oplus.audio.dumpinfo.type', value) with shell-metacharacter payloads and ctl.start=audiodumpinfo, which launches /system_ext/bin/audioDumpInfo as UID 0 in the dumpstate SELinux domain and passes the unsanitized property into system(), yielding root command execution with no Android permissions.

- **Languages:** Splunk SPL, Microsoft KQL, Sigma
- **ATT&CK:** T1575, T1623, T1623.001, T1404
- **Data sources:** mobile_threat_defense_process_telemetry, android_binder_service_logs, android_enterprise_security_log
- **Severity:** critical
- **Confidence:** high

### Splunk SPL

```spl
index=mobile_edr sourcetype="mtd:process_event"
| eval shell_meta=if(match(property_value, "[;|`$<>]"), 1, 0)
| where (binder_service="AtlasService" AND binder_method="setEvent" AND match(binder_args,"atlas_event_multimedia_audio_dumpsys"))
   OR (process_path="/system_ext/bin/audioDumpInfo")
   OR (property_name="oplus.audio.dumpinfo.type" AND shell_meta=1)
   OR (control_property="ctl.start" AND control_value="audiodumpinfo")
| eval caller_is_thirdparty=if(caller_uid!=0 AND NOT match(caller_package,"^com\.oneplus\.|^com\.oppo\.|^com\.android\."),1,0)
| stats count min(_time) as first_seen max(_time) as last_seen values(property_value) as injected_values by device_id, caller_package, caller_uid, process_path, selinux_context, caller_is_thirdparty, shell_meta
| where caller_is_thirdparty=1 OR shell_meta=1
```

### Microsoft KQL

```kql
AndroidProcessEvents_CL
| where TimeGenerated > ago(24h)
| where ProcessPath_s has "audioDumpInfo"
   or (BinderService_s == "AtlasService" and BinderMethod_s == "setEvent" and BinderArgs_s has "atlas_event_multimedia_audio_dumpsys")
   or (PropertyName_s == "oplus.audio.dumpinfo.type" and PropertyValue_s matches regex @"[;|`$<>]")
   or (ControlProperty_s == "ctl.start" and ControlValue_s == "audiodumpinfo")
| extend IsThirdPartyCaller = iff(CallerUid_d != 0 and CallerPackage_s !startswith "com.oneplus." and CallerPackage_s !startswith "com.oppo." and CallerPackage_s !startswith "com.android.", true, false)
| project TimeGenerated, DeviceId_g, CallerPackage_s, CallerUid_d, ProcessPath_s, SelinuxContext_s, PropertyValue_s, IsThirdPartyCaller
| where IsThirdPartyCaller == true
```

### Sigma

```yaml
title: OxygenOS AtlasService Confused-Deputy Property Injection to audioDumpInfo Command Injection
id: 7a1e2f3c-9b4d-4e6a-8c2f-1d3e5b6a7c9d
status: experimental
description: Detects the stage-one exploit chain against OnePlus/OPPO OxygenOS AtlasService, where a zero-permission app invokes the setEvent Binder method with the atlas_event_multimedia_audio_dumpsys event name to inject shell metacharacters into the oplus.audio.dumpinfo.type system property, achieving command injection as root via the audioDumpInfo binary in the dumpstate SELinux domain.
references:
    - https://blog.nns.ee/2026/09/24/oneplus-root
    - https://thehackernews.com/2026/09/unpatched-oneplus-flaws-let-installed.html
author: Threadlinqs Team
date: 2026-09-27
tags:
    - attack.execution
    - attack.privilege-escalation
    - attack.t1575
    - attack.t1623
    - attack.t1623.001
    - attack.t1404
    - attack.exploit.oneplus-atlasservice
logsource:
    category: process_creation
    product: android
detection:
    selection_process:
        ProcessPath|contains: '/system_ext/bin/audioDumpInfo'
    selection_binder:
        BinderService: 'AtlasService'
        BinderMethod: 'setEvent'
        BinderArgs|contains: 'atlas_event_multimedia_audio_dumpsys'
    selection_property:
        PropertyName: 'oplus.audio.dumpinfo.type'
        PropertyValue|re: '[;|`$<>]'
    selection_ctl:
        ControlProperty: 'ctl.start'
        ControlValue: 'audiodumpinfo'
    condition: 1 of selection_*
falsepositives:
    - OEM diagnostic/QA tooling legitimately invoking audioDumpInfo via authorized vendor debug harnesses (rare on production-shipped devices)
level: critical
```

**Known false positives:**

- OEM factory-test or QA tooling on engineering/userdebug builds legitimately exercising the audioDumpInfo debug path
- MTD telemetry parsing errors misclassifying a benign property value as containing shell metacharacters

**Tuning notes:** Baseline and exclude signed OEM diagnostic/QA processes that legitimately invoke audioDumpInfo (match on package signing hash, not name alone); tighten the shell-metacharacter regex if the MTD vendor's telemetry already escapes property values before forwarding, and require caller_is_thirdparty=1 for high-confidence alerting rather than shell_meta alone.

### 8 more detection rules (Splunk SPL, Microsoft KQL, Sigma), unlock with TL Creds

- KQL: OxygenOS AtlasService Confused-Deputy Property Injection → audioDumpInfo Command Injection (locked: unlock with TL Creds)
- KQL: olc2 Vendor HAL doShell() Confused-Deputy Root Shell & Kernel-Module Capability Escalation — Post-Exploitation (locked: unlock with TL Creds)
- KQL: Post-Root Staged classes.dex Execution & Cross-App Private Data Access — C2/Lateral Movement Equivalent (locked: unlock with TL Creds)
- Sigma: OxygenOS AtlasService Confused-Deputy Property Injection → audioDumpInfo Command Injection (locked: unlock with TL Creds)
- Sigma: olc2 Vendor HAL doShell() Confused-Deputy Root Shell & Kernel-Module Capability Escalation — Post-Exploitation (locked: unlock with TL Creds)
- Sigma: Post-Root Staged classes.dex Execution & Cross-App Private Data Access — C2/Lateral Movement Equivalent (locked: unlock with TL Creds)
- SPL: olc2 Vendor HAL doShell() Confused-Deputy Root Shell & Kernel-Module Capability Escalation — Post-Exploitation (locked: unlock with TL Creds)
- SPL: Post-Root Staged classes.dex Execution & Cross-App Private Data Access — C2/Lateral Movement Equivalent (locked: unlock with TL Creds)

Sign up free to unlock the detection rules: https://threadlinqs.com/?modal=signup

## Sources

- [Getting root on OnePlus 15 from an untrusted app, via an audio debug service and a vendor HAL](https://blog.nns.ee/2026/09/24/oneplus-root)
- [Unpatched OnePlus Flaws Let Installed Android Apps Gain Root Without Permissions](https://thehackernews.com/2026/09/unpatched-oneplus-flaws-let-installed.html)
- [OnePlus 15 Flaws Let Hackers Install Apps With Zero Permissions and Gain Root Access](https://cybersecuritynews.com/oneplus-15-flaws-zero-permission-apps/)
- [OnePlus Root Vulnerability: 159 Days, Still Unpatched](https://shattered.io/oneplus-root-vulnerability-159-days-unpatched-2026/)
- [OnePlus Root Flaws Unpatched: 0 CVE, 0 Fix Yet 2026](https://tech-insider.org/oneplus-root-vulnerability-atlasservice-olc2-2026/)
- [OnePlus 15 root exploit lets malicious apps gain control](https://cybernews.com/security/oneplus-15-root-flaw-malicious-app-oxygenos/)
- [An app with no permissions can gain root access on OnePlus and Oppo phones](https://www.notebookcheck.net/An-app-with-no-permissions-can-gain-root-access-on-OnePlus-and-Oppo-phones.1409406.0.html)
- [OnePlus 15 Flaws Let Zero-Permission Apps Gain Root Access Through OxygenOS Services](https://www.cryptika.com/oneplus-15-flaws-let-zero-permission-apps-gain-root-access-through-oxygenos-services/)
- [OEMpocalypse Now: A Generic Exploitation Strategy from Android untrusted app to root](https://calif.io/research/oempocalypse)
- [OEMpocalypse Now](https://blog.calif.io/p/oempocalypse-now)
- [Unprivileged Android app gains root on latest flagships, researcher shows](https://cybernews.com/security/android-oem-vulnerability-unprivileged-app-root)

## Full data

The other 8 detection rules (Splunk SPL / Microsoft KQL / Sigma) unlock with TL Creds; a free account includes daily creds: https://threadlinqs.com/?modal=signup
Indicator values unlock with TL Creds, at a lower price on Red and Purple; AI agents can query rules and IOCs through the Threadlinqs MCP server (Purple): https://intel.threadlinqs.com/mcp

Canonical: https://intel.threadlinqs.com/threat/TL-2026-2683
