vercel-labs / vercel-labs/native

中文:macOS 签名缺少 Mach-O headerpad,导致 GPU 应用启动崩溃

Open
#279 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Zig
Stars
7.7k
Forks
314
Avg merge
5h
Merged PRs (30d)
13

Description

问题

在 macOS 上,使用 Native SDK 构建包含 chromeless window 和 GPU surface 的应用时,未签名二进制可以运行;但对同一个二进制执行 ad-hoc 签名后,首次 GPU frame 触发窗口激活时会崩溃。

签名命令本身和 codesign --verify --deep --strict 都可能成功,因此仅检查签名结果无法发现这个问题。

复现

在一个包含 chromeless window 和 GPU surface 的最小应用中:

native build
native package --target macos --signing adhoc --output MyApp.app
codesign --verify --deep --strict MyApp.app
open MyApp.app

现象:

  • 直接运行未签名的构建产物可以正常启动。
  • ad-hoc 签名后的应用在首次 GPU frame、窗口变为 key window 的路径上崩溃。
  • codesign --verify --deep --strict 仍报告签名有效。
  • 使用足够的 Mach-O 头部预留空间重新构建后,签名不会覆盖代码,应用可以持续运行。

根因分析

macOS 可执行文件在链接时没有为后续的 LC_CODE_SIGNATURE 留出足够的头部空间。签名阶段新增该 load command 时会覆盖靠近 Mach-O 头部的已有指令。签名工具随后会对被覆盖后的文件计算并验证代码目录,所以 codesign --verify 仍可能通过,但运行时会跳转到已损坏的函数指令。

build/app.zig 创建应用可执行文件时,为 macOS 设置:

if (target.result.os.tag == .macos) {
    exe.headerpad_size = 0x4000;
}

可以稳定消除该崩溃。等效的链接器 headerpad 配置也可以接受。

建议

  1. 在 macOS 应用可执行文件的构建路径中设置 headerpad_size,或传递等效的 -headerpad_max_install_names
  2. 增加回归测试:构建 chromeless GPU 应用,执行 ad-hoc 签名和 codesign --verify --deep --strict,再实际启动并保持运行一段时间。
  3. 将签名后的启动验证纳入 macOS 打包验收,避免只用 codesign --verify 判断包可运行。

该问题与 #115 的带空格输出路径导致签名命令失败不同;这里的签名命令和验证都成功,但签名写入位置破坏了可执行文件代码。

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in build/app.zig at application executable creation and inspect the macOS target configuration. Reproduce with a chromeless GPU app using native build, native package, codesign verification, and launch; confirm the signed app remains running through its first GPU frame. Done means the header-reservation change is applied and a regression check covers signing and startup.

Written by the indexing model from the issue text.

Assessment

Tech stack
macos, zig
Domain
build-system, desktop, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.