Apple’s recent release of iOS 18.4 has introduced a significant bug impacting dynamic symbol resolution on devices equipped with Pointer Authentication Code (PAC) technology. This issue, first identified by reverse-engineering expert Fabien Perigaud, affects applications that rely on dynamic library loading and symbol resolution, leading to potential crashes and instability.
Understanding the Bug
The problem arises when applications utilize the `dlsym()` function to resolve symbols dynamically, particularly on devices powered by the A15 SoC, such as the iPhone SE 3rd generation. In iOS 18.4, an oversight in the dynamic linker (`dyld`) implementation results in certain symbols, notably `strcmp`, being incorrectly signed or unsigned. This mismanagement leads to application crashes due to kernel protection failures.
Technical Breakdown
When an application calls `dlsym()` to resolve symbols like `strcmp`, which are re-exported from `libsystem_platform.dylib` with the `EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER` flag, the function pointer returned should have its PAC signature stripped before conversion to an offset. However, in iOS 18.4, this stripping process is omitted, causing the pointer to be signed twice. This double signing results in either an invalid signature or an unsigned pointer, leading to application crashes.
Perigaud’s investigation revealed that the absence of the `XPACI` instruction in the `dyld` code is the root cause. This instruction, present in previous versions like iOS 18.3.2, is responsible for stripping the PAC signature from the pointer returned by the resolver function. Its omission in iOS 18.4 leads to the observed behavior.
Further experiments confirmed that the pointer is treated as a kernel pointer during the second signing operation, contrary to ARMv8.6-A architecture specifications. This misinterpretation results in the pointer being signed with all upper bits set to 1, which, when XORed with the original pointer, cancels out the first signature or produces an incorrect one.
Implications for Developers
This bug has significant implications for developers, especially those working on applications that dynamically load libraries or use system functions through `dlsym()`. While not all applications crash due to this issue, those that do face critical stability problems. Developers have found temporary workarounds by manually stripping and re-signing the pointers, but this is not a sustainable solution.
Apple’s Response
As of now, Apple has not officially acknowledged this bug. However, given its severity, a fix is expected in an upcoming update. The community is hopeful that Apple will address this issue promptly to prevent further disruptions in app functionality and security.
Broader Context
This incident underscores the complexities involved in implementing security features like PAC in modern operating systems. It also highlights the importance of thoroughly testing and validating system updates, especially those involving low-level system interactions. Developers and users alike are advised to stay tuned for Apple’s response and subsequent updates to resolve this critical issue.