# How to Resolve the EXC_GUARD/GUARD_TYPE_MACH_PORT Crash in vphone-cli Using --force-exc-guard

> Resolve EXC_GUARD/GUARD_TYPE_MACH_PORT crashes in vphone-cli by understanding mach-port issues and using the --force-exc-guard flag for a no-op patch, enabling successful virtual machine boots.

- Repository: [Lakr/vphone-cli](https://github.com/Lakr233/vphone-cli)
- Tags: how-to-guide
- Published: 2026-09-08

---

**The EXC_GUARD/GUARD_TYPE_MACH_PORT crash occurs when the iOS kernel detects invalid mach-port usage by system services or crash-reporting SDKs, and the `--force-exc-guard` flag resolves it by applying a no-op patch to the `_thread_guard_violation` function in [`KernelPatcher.swift`](https://github.com/Lakr233/vphone-cli/blob/main/KernelPatcher.swift), allowing the virtual machine to boot successfully.**

`vphone-cli` is an open-source tool that boots iOS virtual machines by dynamically patching kernel and firmware components. When launching iOS 18 bases or VMs containing third-party crash reporters, users encounter a fatal **EXC_GUARD/GUARD_TYPE_MACH_PORT** exception that triggers a crash loop. This article explains the architectural root cause of this guard violation and how the `--force-exc-guard` command-line flag forces the kernel-level patch required to bypass it.

## What Causes the EXC_GUARD/GUARD_TYPE_MACH_PORT Crash?

The crash originates from the kernel's `_thread_guard_violation` function, which treats specific mach-port operations as fatal errors. `vphone-cli` normally operates with a patched research kernel, but certain iOS components trigger guard violations that the default patching logic does not anticipate.

### iOS 18 User-Space Violations

**iOS 18 bases** (such as 18.6.2) contain user-space components—specifically `runningboardd` and `SpringBoard`—that deliberately trigger a **GUARD_TYPE_MACH_PORT** violation with flavor code 10. The research kernel treats this as a fatal exception, causing a crash-loop that prevents the UI layer from initializing. This behavior is specific to iOS 18's process management architecture, where the system attempts to swap exception ports in ways that violate the kernel's guard policies.

### Third-Party Crash Reporting SDKs

On other iOS bases (such as 26.x), the VM may boot normally until **third-party crash-reporting SDKs** (Bugly, Crashlytics, KSCrash) invoke `task_swap_exception_ports()`. The patched kernel interprets these calls as fatal **GUARD_TYPE_MACH_PORT** violations with `KOBJECT_REPLY_PORT_SEMANTICS`, immediately terminating the process. According to the source analysis, this is documented in upstream issue #291.

## How the --force-exc-guard Flag Resolves the Crash

The resolution involves rewriting the kernel's guard-handling logic to return immediately instead of raising a fatal exception. The `--force-exc-guard` flag ensures this patch is applied regardless of automatic iOS version detection.

### The Kernel Patching Logic

In [`sources/FirmwarePatcher/Kernel/KernelPatcher.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/FirmwarePatcher/Kernel/KernelPatcher.swift), the boolean flag `applyExcGuard` controls whether the guard bypass is installed:

```swift
// KernelPatcher.swift
public var applyExcGuard: Bool = false          // ← line 27
...
if isDev || applyExcGuard {                     // ← line 61
    patchExcGuardBehavior()                     // ← line 62
}

```

The `patchExcGuardBehavior()` function replaces the instruction sequence in `_thread_guard_violation` with a no-op that simply returns, effectively ignoring EXC_GUARD faults.

### Pipeline Integration

The `FirmwarePipeline` orchestrator determines when to enable the patch via the logic in [`sources/FirmwarePatcher/Pipeline/FirmwarePipeline.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/FirmwarePatcher/Pipeline/FirmwarePipeline.swift) (line 34):

```swift
let applyExcGuard = iosBaseIs18 || forceExcGuard

```

- `iosBaseIs18` is automatically detected by parsing the iPhone's `BuildManifest.plist` for iOS 18.x signatures.
- `forceExcGuard` is the boolean value passed from the `--force-exc-guard` command-line argument.

When the flag is provided, `applyExcGuard` evaluates to `true`, causing `KernelPatcher` to invoke `patchExcGuardBehavior()` and rewrite the guard-violation instruction sequence. The binary diff for this operation is documented as patch entry 27 in [`research/0_binary_patch_comparison.md`](https://github.com/Lakr233/vphone-cli/blob/main/research/0_binary_patch_comparison.md) (lines 119-121).

## Usage Examples

### Force the Patch via CLI

To manually apply the EXC_GUARD bypass when patching a VM named "myVM":

```bash
vphone-cli fw patch myVM --variant regular --force-exc-guard

```

The flag is parsed in [`sources/vphone-cli/VPhoneFWCLI.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/vphone-cli/VPhoneFWCLI.swift) (lines 94-99) and forwarded to the `FirmwarePipeline` constructor.

### Using the Makefile Shortcut

For automated build pipelines, the project Makefile supports the `FORCE_EXC_GUARD` variable:

```bash
make fw_patch REGULAR_VARIANT=1 FORCE_EXC_GUARD=1

```

When `FORCE_EXC_GUARD=1` is set, the Makefile injects `--force-exc-guard` into the CLI invocation (lines 354-356).

### Verifying Patch Application

After patching, the CLI outputs the number of applied patches. Confirm the EXC_GUARD patch (entry 27) is present:

```text
[fw patch] applied 27 patches for regular

```

You can also inspect the generated `PatchRecord` for `_thread_guard_violation` in the pipeline debug output, or review the binary diff documentation in [`research/0_binary_patch_comparison.md`](https://github.com/Lakr233/vphone-cli/blob/main/research/0_binary_patch_comparison.md).

## Summary

- The **EXC_GUARD/GUARD_TYPE_MACH_PORT** crash occurs when iOS 18 system services (`runningboardd`, `SpringBoard`) or third-party SDKs trigger mach-port guard violations treated as fatal by the research kernel.
- The kernel patch replaces the `_thread_guard_violation` function with a no-op return, bypassing the fatal error condition.
- iOS 18 bases automatically receive this patch via `iosBaseIs18` detection in [`FirmwarePipeline.swift`](https://github.com/Lakr233/vphone-cli/blob/main/FirmwarePipeline.swift) (line 34).
- Non-iOS 18 bases require the `--force-exc-guard` flag to manually enable `applyExcGuard` in [`KernelPatcher.swift`](https://github.com/Lakr233/vphone-cli/blob/main/KernelPatcher.swift) (line 27).
- The patch is implemented as binary patch entry 27, documented in the project's research notes.

## Frequently Asked Questions

### What is EXC_GUARD in the iOS kernel?

**EXC_GUARD** is a kernel-level exception mechanism that validates mach-port usage and semantics. When user-space code violates port guards—such as calling `task_swap_exception_ports()` with invalid parameters—the kernel raises an `EXC_GUARD` exception. In the context of `vphone-cli`, the research kernel treats these as fatal errors unless the `_thread_guard_violation` handler is patched to ignore them.

### Why does vphone-cli apply the patch automatically only for iOS 18?

The tool detects the iOS base version by parsing `BuildManifest.plist`. When `iosBaseIs18` evaluates to `true` (line 34 in [`FirmwarePipeline.swift`](https://github.com/Lakr233/vphone-cli/blob/main/FirmwarePipeline.swift)), the pipeline automatically sets `applyExcGuard` to `true` because iOS 18's `runningboardd` and `SpringBoard` are known to trigger flavor-10 `GUARD_TYPE_MACH_PORT` violations during normal boot. This prevents the mandatory crash-loop that would otherwise prevent the UI from loading.

### Is it safe to use --force-exc-guard on non-iOS 18 bases?

Yes. The patch is functionally safe on any iOS base, as it only changes the kernel's response to guard violations from fatal to ignored. However, it is only necessary when running crash-reporting SDKs (Bugly, Crashlytics, etc.) that call `task_swap_exception_ports()`. Without these components, the patch has no functional effect but adds minimal overhead to the boot process.

### How can I verify the EXC_GUARD patch was applied successfully?

After running `vphone-cli fw patch`, check the console output for the patch count (e.g., "applied 27 patches"). The EXC_GUARD modification corresponds to patch entry 27 in the binary patch table. For manual verification, inspect the generated kernel binary or review the patch documentation in [`research/0_binary_patch_comparison.md`](https://github.com/Lakr233/vphone-cli/blob/main/research/0_binary_patch_comparison.md) at lines 119-122, which details the specific instruction sequence replaced in `_thread_guard_violation`.