Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-43655-AppleM2ScalerCSCDriver-UAF — Public disclosure for CVE-2026-43655 AppleM2ScalerCSCDriver use-after-free | Kitploit
Tools/GitHubGitHub/somisomair/cve-2026-43655-applem2scalercscdriver-uaf
iOS SecurityMemory ForensicsVulnerability AnalysisExploitationMobile SecurityHardware SecurityBinary Exploitation
GitHubsomisomair/cve-2026-43655-applem2scalercscdriver-uaf

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-43655-AppleM2ScalerCSCDriver-UAF

Public disclosure for CVE-2026-43655 AppleM2ScalerCSCDriver use-after-free

View Repository
1 month agoNot yet reviewed

CVE-2026-43655: AppleM2ScalerCSCDriver shared scheduler use-after-free

Public technical disclosure for CVE-2026-43655, an AppleM2ScalerCSCDriver / IOSurfaceAccelerator use-after-free reachable from the default iOS app sandbox with no special entitlements.

Apple addressed this issue in iOS 26.5 / iPadOS 26.5 / macOS Tahoe 26.5. This repository contains the Objective-C proof-of-concept source, minimal entitlements, a built IPA, and the technical write-up needed to understand and reproduce the issue on an affected device.

Summary

The bug is a teardown/lifetime error in the scaler scheduler. A user process can submit asynchronous scaler operations, close the IOSurfaceAcceleratorClient connection that owns those operations, and leave stale entries behind in a driver-global scheduler structure. A later scheduler pass can then process entries that still point at operation storage that was already freed and reused.

The PoC demonstrates the lifetime bug with two distinct marker values:

  • victim connection marker: 0xDEAD0001
  • spray/replacement connection marker: 0xBEEF0002

The victim connection submits async operations and is then closed. Replacement connections are opened afterward and set their own marker to 0xBEEF0002. When the next scaler scheduling cycle runs, the fault observes the replacement marker (x9 = 0x00000000BEEF0002), not the victim marker. That proves the scheduler read from an operation slot that had been freed and then reallocated to a different connection.

Affected configuration

  • Observed affected OS: iOS 26.4
  • Fixed in: iOS 26.5 / iPadOS 26.5 / macOS Tahoe 26.5
  • Kext: com.apple.driver.AppleM2ScalerCSCDriver
  • User-client path: IOSurfaceAcceleratorClient
  • App entitlements used by the PoC: get-task-allow only
  • No jailbreak, no platform entitlement, no special Apple-private entitlement

Root cause

AppleM2ScalerCSCDriver keeps scheduler state shared across scaler clients. The relevant lifetime mismatch is:

  1. A client submits async scaler operations.
  2. Those operations are inserted into scheduler-owned state.
  3. The client connection is closed with IOServiceClose.
  4. The per-client operation storage is freed.
  5. The shared scheduler state is not fully purged of entries belonging to the closed client.
  6. A later scheduler pass processes stale operation pointers.

The teardown path does not remove the closing client's pending scheduler entries from the shared scheduler heap. The scheduler later reads and writes fields through those stale pointers.

Important fields observed during analysis:

OffsetScheduler behavior
operation + 0xc94read as the credit/marker value used by the credit-resolution path
operation + 0xc1cwritten by the scheduler credit accounting path
operation + 0x1fe4written by the scheduler state/flag update path

The operation allocator behavior makes the bug observable: freed operation slots can be reused by later operations from different connections. By closing a victim connection and immediately spraying new connections, the PoC can cause stale scheduler entries to point at memory now owned by the spray connections.

Why x9 = 0xBEEF0002 proves UAF

The PoC uses a victim/spray distinction:

  1. Victim connection sets marker 0xDEAD0001.
  2. Victim submits 50 async scaler operations.
  3. Victim connection is closed, freeing the victim operation objects.
  4. Spray connections set marker 0xBEEF0002.
  5. Spray operations reuse the freed operation pool slots.
  6. The scheduler later processes the stale victim scheduler entries.

If the scheduler were still reading live victim-owned objects, the observed value would be 0xDEAD0001. Instead, the reproduced fault observes 0xBEEF0002, the value written by the replacement spray connections. That is the key proof that the scheduler is dereferencing a stale pointer into freed-and-reused kernel memory.

This also shows cross-connection impact: the scheduler entry was created by one connection, but the memory it later touched had been recycled for another connection. In reproduced runs, the final scheduler activity could be driven by normal SpringBoard/compositor/UI activity rather than the original PoC process.

Impact

  • Kernel read from freed/reused operation memory.
  • Kernel writes to fixed offsets in freed/reused operation memory during scheduler accounting/state updates.
  • Cross-connection effect because the scheduler heap is shared across scaler users.
  • Cross-process trigger behavior because any later process that drives scaler scheduling can cause the stale entry to be processed.
  • Stale scheduler state can survive the original PoC app's immediate execution window and trigger on a later scheduler cycle.

The public Apple advisory describes the impact as: “An app may be able to cause unexpected system termination or read kernel memory.”

Physical-device reproduction sequence

Important reproduction detail: after tapping TEARDOWN UAF, the device does not necessarily panic immediately. The PoC first primes stale scheduler state. The bug triggers on the next scaler scheduling cycle, which in practice occurs when SpringBoard/compositor activity drives the scaler. In my physical-device reproduction, I triggered that scheduler cycle by tapping/interacting with the Dynamic Island after the PoC finished priming the stale scheduler state.

Steps:

  1. Reboot the affected device before running the PoC.
  2. Install and launch ScalerTeardownUAF.ipa.
  3. Tap TEARDOWN UAF.
  4. The PoC opens a victim AppleM2ScalerCSCDriver connection.
  5. The PoC creates source/destination IOSurface objects.
  6. The PoC submits a synchronous baseline scaler operation.
  7. The PoC sets selector 10 credit/marker data to 0xDEAD0001 on the victim connection.
  8. The PoC submits 50 async operations on the victim connection.
  9. The PoC closes the victim connection with IOServiceClose, freeing victim-owned operation objects while stale scheduler entries remain.
  10. The PoC opens 50 spray connections.
  11. Each spray connection sets selector 10 credit/marker data to 0xBEEF0002.
  12. The PoC submits additional async operations on the spray connections to reuse freed operation slots and keep scheduler pressure active.
  13. When the app prompts for the trigger, tap/interact with the Dynamic Island to cause SpringBoard/compositor activity and drive the scaler scheduler.
  14. The device panics/reboots when the stale scheduler entry is processed.
  15. After reboot, verify the panic register state contains x9 = 0x00000000BEEF0002.

Expected proof condition:

  • x9 = 0x00000000BEEF0002 means the scheduler read the spray marker from memory that originally belonged to the freed victim operation.
  • 0xBEEF0002 is not the victim marker; it is the replacement connection marker.
  • Therefore the observed scheduler read happened after free and reuse.

PoC behavior

The included source performs the following sequence:

root@kitploit:~
open victim connection
create IOSurface source/destination pair
submit sync baseline scaler request
set victim marker = 0xDEAD0001 through selector 10
submit 50 async scaler operations
close victim connection
open 50 spray connections
set spray marker = 0xBEEF0002 through selector 10
submit repeated async scaler operations on spray connections
wait for SpringBoard/compositor scheduler trigger

The relevant source file is ScalerTeardownUAF.m.

Build

root@kitploit:~
xcrun -sdk iphoneos clang -framework Foundation -framework UIKit -framework IOKit \
  -framework IOSurface -isysroot $(xcrun --sdk iphoneos --show-sdk-path) \
  -arch arm64 -arch arm64e -miphoneos-version-min=16.0 -fobjc-arc \
  -o iPhoneProbe.app/iPhoneProbe ScalerTeardownUAF.m
ldid -S entitlements.plist iPhoneProbe.app/iPhoneProbe
mkdir -p /tmp/pkg/Payload
cp -r iPhoneProbe.app /tmp/pkg/Payload/
cd /tmp/pkg && zip -qr ScalerTeardownUAF.ipa Payload

Repository files

Timeline

  • Initial crash found while testing AppleM2ScalerCSCDriver behavior.
  • UAF proven with victim/spray marker distinction: victim 0xDEAD0001, spray 0xBEEF0002.
  • Physical-device reproduction confirmed by triggering the next scaler scheduling cycle through Dynamic Island / SpringBoard compositor activity.
  • Apple fixed the issue in the 26.5 release line and assigned CVE-2026-43655.
Download Tool
FileDescription
ScalerTeardownUAF.mObjective-C PoC source implementing the victim close + spray reuse sequence.
ScalerTeardownUAF.ipaBuilt IPA reproduction artifact.
entitlements.plistMinimal entitlement file containing get-task-allow.