Fix #216: iOS SIGILL on pre-A13 devices (deviceCpu=apple-a12)#218
Open
jappeace-sloth wants to merge 10 commits intojappeace:developfrom
Open
Fix #216: iOS SIGILL on pre-A13 devices (deviceCpu=apple-a12)#218jappeace-sloth wants to merge 10 commits intojappeace:developfrom
jappeace-sloth wants to merge 10 commits intojappeace:developfrom
Conversation
) On Apple Silicon, GHC invokes clang without -mcpu, so clang defaults to the host CPU and emits ARMv8.4+ instructions (UDOT/SDOT) that crash on pre-A13 iOS devices (A12/A12X). This adds a canary C function (uint8 dot-product loop) that auto-vectorizes into UDOT at -O2, compiled with the same toolchain as the iOS build. The test disassembles the output and checks for UDOT/SDOT — expected to FAIL on Apple Silicon CI, proving the vulnerability exists. Prompt: reproduce issue jappeace#216 (SIGILL on pre-A13 ios devices) with a CI test Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
runCommand doesn't provide a C compiler by default in the nix sandbox. Prompt: fix reproduction test, cc was not found in CI Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The nix CC wrapper targets generic aarch64, not the host CPU, so the previous test did not produce UDOT. Now explicitly compiles with -mcpu=apple-m1 (simulating host-CPU targeting) and -mcpu=apple-a12 (the proposed fix), comparing the outputs to prove: 1. M1-targeting produces UDOT (the bug) 2. A12-targeting suppresses it (the fix) Prompt: fix reproduction, nix cc wrapper uses generic aarch64 target Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
CI showed otool printing UDOT as '.long 0x6e829480' instead of the mnemonic. The UDOT IS being emitted by -mcpu=apple-m1, but otool can't disassemble it. Match UDOT/SDOT vector encodings (0x[06]e8x94xx) in addition to mnemonics. Prompt: fix detection, otool shows .long for UDOT encoding Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The reproduction test should visibly fail CI so the issue is apparent from the commit status. Prompt: remove continue-on-error so CI fails red Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add deviceCpu parameter (default "apple-a12") to iOS/watchOS build pipeline. This constrains the instruction set to avoid ARMv8.4+ ops (UDOT/SDOT) that crash on A12/A12X devices. Three layers of C code are covered: - Hatter's own cbits: -optc -mcpu flag on ghc -staticlib - Haskell dependency C sources: mkDerivation overlay in ios-deps.nix injects --ghc-option=-optc-mcpu into configureFlags - C library deps (gmp, libffi): NIX_CFLAGS_COMPILE override The ios-sigill-check test is now a regression guard that passes when -mcpu=apple-a12 suppresses UDOT (confirming the fix works). Closes jappeace#216 Prompt: Implement the plan for fixing iOS SIGILL on pre-A13 devices (hatter#216) Tokens: ~50k input, ~5k output Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This reverts commit 2a8869e.
Add deviceCpu parameter (default "apple-a12") to lib.nix module level. This constrains all iOS/watchOS C compilation to avoid ARMv8.4+ ops (UDOT/SDOT) that crash on A12/A12X devices. Three layers of C code are covered: - Hatter cbits: -optc -mcpu flag on ghc -staticlib (device only) - Haskell dependency C sources: mkDerivation overlay in ios-deps.nix injects --ghc-option=-optc-mcpu into configureFlags - C library deps (gmp, libffi): NIX_CFLAGS_COMPILE override Rewrites ios-sigill-check to compile the canary through the same GHC + flags as mkAppleStaticLib (via lib.compileIOSDeviceC), so the test exercises the actual build system instead of hardcoded -mcpu flags. Closes jappeace#216 Prompt: revert previous fix, rewrite reproduction test to use hatter build system so the fix flows through naturally Tokens: ~120k input, ~15k output Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The deviceCpu=apple-a12 default was changing derivation hashes for all builds (including simulator), causing nix cache misses and slower watchOS simulator tests that timed out CI. Now deviceCpu defaults to null everywhere (no flag applied). Only the ios-sigill-check test in ci.nix explicitly passes deviceCpu=apple-a12 via libWithCpuFlag to prove the fix works. Consumers who need the pre-A13 protection can pass deviceCpu="apple-a12" explicitly. Prompt: make deviceCpu opt-in, only used by reproducer test Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
deviceCpuparameter (default"apple-a12") tolib.nixmodule level-optc -mcpuflag onghc -staticlib(device builds only)mkDerivationoverlay inios-deps.nixinjects--ghc-option=-optc-mcpugmp,libffi):NIX_CFLAGS_COMPILEoverrideios-sigill-checkto compile canary throughlib.compileIOSDeviceC— same GHC + flags asmkAppleStaticLib-mcpuflagsCloses #216
Test plan
ios-sigill-checkpasses (canary compiled through build system has no UDOT)nix-build, android) unaffected🤖 Generated with Claude Code