Skip to content

pe_v1: recognize own search pages instead of re-racing them as lost races - #990

Open
kolbicz wants to merge 1 commit into
opa334:3.xfrom
kolbicz:ownpage-marker-optimization
Open

pe_v1: recognize own search pages instead of re-racing them as lost races#990
kolbicz wants to merge 1 commit into
opa334:3.xfrom
kolbicz:ownpage-marker-optimization

Conversation

@kolbicz

@kolbicz kolbicz commented Sep 2, 2026

Copy link
Copy Markdown

Summary

pe_v1 stamps its own search-mapping pages with randomMarker — the same value
physical_oob_read_mo uses as its lost-race sentinel. A successful OOB read that
lands on one of our own search pages therefore reads back randomMarker, is
judged a lost race, and is re-raced up to the retry cap before the scan skips the
page. An own page is a known, safe value that can never hold a sprayed PCB, so
that work is redundant.

This stamps the search pages with a distinct marker (randomMarker ^ K) so an
own-page read is recognized on the first attempt and the scan advances. The
lost-race sentinel and the physically-contiguous-mapping stamp are unchanged;
only the search-mapping stamp moves.

This is an optimization, not a bug fix. Acquisition behaviour is unchanged
apart from a negligible marker-collision possibility: a sprayed PCB whose first
64 bits happen to equal randomMarkerOwned would now be skipped by the new
branch. The scan already has the same class of collision against the lost-race
sentinel (randomMarker) inside physical_oob_read_mo; this adds one more
distinct point, so the probability of missing a real PCB goes from ~2⁻⁶⁴ to
~2⁻⁶³ — both cryptographically negligible, but not literally zero.

Background

We stumbled on this while looking for scan-efficiency wins on A18 — where
fragmented search pools make own-page reads frequent enough to matter — but the
change stands on logical grounds for every device that runs pe_v1: the
own-page/sentinel collision is in the scan logic itself, independent of hardware.

The collision

  • physical_oob_read_mo pre-stamps the buffer/target with randomMarker and
    treats a read that still returns randomMarker as a lost race → retry
    (if (marker != randomMarker) readRaceSucceeded = true;).
  • The search mappings are stamped with that same randomMarker.
  • So a genuine OOB read landing on an own search page is indistinguishable from a
    lost race and is re-raced up to the cap.

The change

Add randomMarkerOwned = randomMarker ^ 0x9e3779b97f4a7c15, stamp the search
pages with it, and recognize it in the scan loop (own page → skip). Because it
differs from randomMarker, physical_oob_read_mo returns success on the first
read of an own page instead of exhausting the retry budget.

Both kernel exploits share this scan logic, so the change touches both; no
post-exploitation path is affected:

  • Exploits/DarkSword/DarkSword.m (arm64e)
  • Exploits/ClearSword/exploit/{common.h,poc.c} (arm64)

Verification (on device)

Path Device Result
ClearSword (arm64) iPad Pro 2017 / A10X full jailbreak succeeds — no regression
DarkSword (arm64e) iPhone 15 Pro Max / A17 Pro, iOS 17.3.1 own-page reads go from unrecognized (own=0) to recognized (own>0); acquires identically

The DarkSword figure was measured in a separate build of the same scan code
instrumented with an own-page counter; the change here adds no logging. The size
of the saving scales with how often the scan lands on its own pages — larger on
fragmented / memory-shaped pools, negligible on standard geometry. No wall-clock
speedup is claimed on the standard path.

…aces

The search-mapping pages are stamped with randomMarker, which is also the
lost-race sentinel in physical_oob_read_mo. So a successful OOB read that
lands on one of our own search pages reads back randomMarker, is judged a
lost race, and is re-raced up to the retry cap before the scan skips it --
an own page can never hold a sprayed PCB, so that work is redundant.

Stamp the search pages with a distinct randomMarker ^ K so an own-page read
is recognized on the first attempt and the scan advances. The lost-race
sentinel and the physically-contiguous-mapping stamp are unchanged.

Optimization only; acquisition behaviour is unchanged (verified: ClearSword
jailbreaks an A10X device end-to-end; DarkSword acquires identically with the
own-page reads going from unrecognized to recognized). Applies to both the
arm64e (DarkSword) and arm64 (ClearSword) scan paths.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant