(CVE-2024-27791) Apple PMP Firmware Out-of-Bounds Write via ApplePMPv2 writeDashboard

CVE: CVE-2024-27791

Affected Versions: iOS and iPadOS before 16.7.5 and before 17.3; macOS Monterey before 12.7.3; macOS Ventura before 13.6.4; macOS Sonoma before 14.3; tvOS before 17.3

CVSS3.1: 7.1 (High) — CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H

Summary

Product Apple PMP Firmware (ApplePMPv2)
Vendor Apple
Severity High — an app may be able to corrupt co-processor memory
Affected Versions iOS/iPadOS < 16.7.5, < 17.3; macOS Monterey < 12.7.3; macOS Ventura < 13.6.4; macOS Sonoma < 14.3; tvOS < 17.3
Tested Versions macOS 13.3 beta3 (Mac Studio); iOS 16.4 latest beta
CVE Identifier CVE-2024-27791
CVE Description An app may be able to corrupt coprocessor memory due to improper memory buffer operations; addressed via improved validation
CWE Classification(s) CWE-119: Improper Restriction of Operations within Memory Buffer Bounds

CVSS3.1 Scoring System

Base Score: 7.1 (High) Vector String: CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H

Metric Value
Attack Vector (AV) Local
Attack Complexity (AC) Low
Privileges Required (PR) None
User Interaction (UI) Required
Scope (S) Unchanged
Confidentiality (C) None
Integrity (I) High
Availability (A) High

Product Background

The Power Management Processor (PMP) is a co-processor present in Apple Silicon devices, visible in the device tree at pmp@8EC00000. It communicates with the Application Processor (AP) via the RTBuddyV2 mailbox interface. The AP-side IOService driver is ApplePMPv2, which exposes user client methods that allow privileged processes to interact with the PMP firmware:

+-o pmp@8EC00000  <class AppleARMIODevice>
  +-o AppleASCWrapV4
    +-o iop-pmp-nub  <class AppleA7IOPNub>
      +-o RTBuddyV2  <class RTBuddyV2>
        +-o ApplePMPFirmware  <class ApplePMPFirmware>
        +-o PMPEndpoint1  <class RTBuddyEndpointService>
          +-o ApplePMPv2  <class ApplePMPv2>

Technical Details

ApplePMPv2UserClient::externalMethods exposes writeDashboard to user clients. The call chain is:

ApplePMPv2UserClient::externalMethods
  → ApplePMPv2UserClient::writeDashboard
    → ApplePMPv2::writeDashboard

Inside ApplePMPv2::writeDashboard, a user-controlled channel_idx is used to index into the PMP’s shared memory region. The bounds check only verifies that channel_idx does not exceed 383 (8 * 383 = 3064 bytes), but fails to account for the full range of values that can corrupt adjacent co-processor memory:

__int64 __fastcall ApplePMPv2::writeDashboard(ApplePMPv2 *this,
    unsigned int channel_idx, __int64 write_value)
{
    __int64 ret;
    AppleA7IOPNub *iop_nub;
    OSObject *base_addr;

    ret = 0xE00002BCLL;
    iop_nub = (AppleA7IOPNub *)*((_QWORD *)this + 23);
    if ( iop_nub )
    {
        base_addr = (*(__int64 (__fastcall **)(AppleA7IOPNub *))
                      (*(_QWORD *)iop_nub->copyProperty_1))(iop_nub);
        if ( (*(__int64 (__fastcall **)(_QWORD))
               (*(_QWORD *)iop_nub->copyProperty_2))(iop_nub)
             <= (unsigned __int64)(8 * channel_idx) )  // channel_idx must be <= 383
        {
            return 0xE00002C2LL;
        }
        else
        {
            ret = 0LL;
            *((_QWORD *)&base_addr->__vftable + channel_idx) = write_value;
        }
    }
    return ret;
}

Different channel_idx values trigger different behaviour on the PMP co-processor side:

  • Channel 0 — causes a PMP panic (PTD abort)
  • Channel 0xf8 — causes a Data Abort with r22/r23 registers controlled by user-supplied data, as shown in the panic log below
  • Channels 0xf9–0xff — cause a PMP SError (Exception class=0x2f) with full register context and backtrace
  • Other channels — can cause ApplePMGR to panic

Channel 0xf8 Data Abort, showing attacker-controlled register values (r22=0x414141414e4243ff, r23=0x4141414000000000):

panic(cpu 0 caller 0xfffffe0030476540): PMP DATA ABORT
pc=0x0000000001024bd4 Exception class=0x25 (Data Abort taken without a change
in Exception level), IL=1, iss=0x46 far=000000000000000000

Faulting task stack frame:
  r22=0x414141414e4243ff  r23=0x4141414000000000
  r24=0x0000016118b14000  r25=000000000000000000
   sp=0x00000000010b6cd0   lr=0x0000000001030454
   pc=0x0000000001024bd4  psr=0x60000004

Channel 0xf9 SError, demonstrating a full register dump:

panic(cpu 1 caller 0xfffffe002c0d2540): PMP SERROR
Exception class=0x2f (SError interrupt), IL=1, iss=0

  r00=0x0000000080010001  r01=0x000000000000000a
  r16=0x0011110000000103  r20=0x000000000000000a
   pc=0x000000000104aa58  psr=0x600002c5

The vulnerability is reachable by compiling and signing a binary with the com.apple.private.pmp.performance-spi entitlement, or by running as root.

Credit

Pan Zhenpeng of STAR Labs SG Pte. Ltd.

Timeline

  • 2024-01-22 — Patch released: iOS/iPadOS 17.3, macOS Sonoma 14.3, macOS Ventura 13.6.4, macOS Monterey 12.7.3, tvOS 17.3
  • 2024-04-24 — CVE-2024-27791 published by Apple