You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

嵌入应用的Launch Daemon无法启动:启动约束违规排查

问题

我有一个macOS应用,其中嵌入了一个暴露XPC服务的launch daemon。该launch daemon已通过ServiceManagement API成功向launchd注册:

% launchctl print system/com.nsnolan.LockerRoomDaemon                       
system/com.nsnolan.LockerRoomDaemon = {
    active count = 0
    path = (submitted by smd.303)
    type = Submitted
    state = spawn scheduled

    program identifier = Contents/MacOS/LockerRoomDaemon (mode: 2)
    parent bundle identifier = com.nsnolan.LockerRoom
    parent bundle version = 1
    BTM uuid = <redacted>
    default environment = {
        PATH => /usr/bin:/bin:/usr/sbin:/sbin
    }

    environment = {
        XPC_SERVICE_NAME => com.nsnolan.LockerRoomDaemon
    }

    domain = system
    minimum runtime = 10
    exit timeout = 5
    runs = 83
    last exit code = 78: EX_CONFIG

    endpoints = {
        "com.nsnolan.LockerRoomDaemon" = {
            port = 0xfaaab
            active = 0
            managed = 1
            reset = 0
            hide = 0
            watching = 0
        }
    }

    spawn type = interactive (4)
    jetsam priority = 40
    jetsam memory limit (active) = (unlimited)
    jetsam memory limit (inactive) = (unlimited)
    jetsamproperties category = daemon
    submitted job. ignore execute allowed
    jetsam thread limit = 32
    cpumon = default
    job state = spawn failed
    probabilistic guard malloc policy = {
        activation rate = 1/1000
        sample rate = 1/0
    }

    properties = partial import | supports transactions | resolve program | needs LWCR update | has LWCR
}

我使用同一开发者证书(带有相同的团队标识符)为应用和launch daemon签名:

% codesign -d --verbose=4 /User/USER/Library/Developer/Xcode/DerivedData/LockerRoom-eyzvsjkjmatcbndmhghzrtcwfqqf/Build/Products/Debug/LockerRoom.app
Executable=/User/USER/Library/Developer/Xcode/DerivedData/LockerRoom-eyzvsjkjmatcbndmhghzrtcwfqqf/Build/Products/Debug/LockerRoom.app/Contents/MacOS/LockerRoom
Identifier=com.nsnolan.LockerRoom
Format=app bundle with Mach-O thin (arm64)
CodeDirectory v=20400 size=50938 flags=0x0(none) hashes=1581+7 location=embedded
VersionPlatform=1
VersionMin=918016
VersionSDK=918528
Hash type=sha256 size=32
CandidateCDHash sha256=<redacted>
CandidateCDHashFull sha256=<redacted>
Hash choices=sha256
CMSDigest=<redacted>
CMSDigestType=2
Executable Segment base=0
Executable Segment limit=2703360
Executable Segment flags=0x1
Page size=4096
CDHash=<redacted>
Signature size=4792
Authority=Apple Development: yeahrightgetlost@urayahoo.com (<redacted>)
Authority=Apple Worldwide Developer Relations Certification Authority
Authority=Apple Root CA
Signed Time=Jul 27, 2024 at 22:35:20
Info.plist entries=24
TeamIdentifier=<redacted>
Sealed Resources version=2 rules=13 files=4
Internal requirements count=1 size=196

codesign -d --verbose=4 /User/USER/Library/Developer/Xcode/DerivedData/LockerRoom-eyzvsjkjmatcbndmhghzrtcwfqqf/Build/Products/Debug/LockerRoom.app/Contents/MacOS/LockerRoomDaemon 
Executable=/User/USER/Library/Developer/Xcode/DerivedData/LockerRoom-eyzvsjkjmatcbndmhghzrtcwfqqf/Build/Products/Debug/LockerRoom.app/Contents/MacOS/LockerRoomDaemon
Identifier= com.nsnolan.LockerRoomDaemon
Format=Mach-O thin (arm64)
CodeDirectory v=20400 size=8353 flags=0x0(none) hashes=250+7 location=embedded
VersionPlatform=1
VersionMin=918016
VersionSDK=918528
Hash type=sha256 size=32
CandidateCDHash sha256=<redacted>
CandidateCDHashFull sha256=<redacted>
Hash choices=sha256
CMSDigest=<redacted>
CMSDigestType=2
Executable Segment base=0
Executable Segment limit=409600
Executable Segment flags=0x1
Page size=4096
CDHash=<redacted>
Signature size=4792
Authority=Apple Development: yeahrightgetlost@urayahoo.com (<redacted>)
Authority=Apple Worldwide Developer Relations Certification Authority
Authority=Apple Root CA
Signed Time=Jul 27, 2024 at 22:35:18
Info.plist=not bound
TeamIdentifier=<redacted>
Sealed Resources=none
Internal requirements count=1 size=204

该launch daemon未配置RunAtLoad。我尝试从应用发送XPC消息以启动daemon时,观察到以下日志信息:

AMFI: Launch Constraint Violation (enforcing), error info: c[5]p[1]m[1]e[0], (Constraint not matched) launching proc[vc: 3 pid: 1948]: /User/USER/Library/Developer/Xcode/DerivedData/LockerRoom-eyzvsjkjmatcbndmhghzrtcwfqqf/Build/Products/Debug/LockerRoom.app/Contents/MacOS/LockerRoomDaemon, launch type 0, failure proc [vc: 3 pid: 1948]: /User/USER/Library/Developer/Xcode/DerivedData/LockerRoom-eyzvsjkjmatcbndmhghzrtcwfqqf/Build/Products/Debug/LockerRoom.app/Contents/MacOS/LockerRoomDaemon

ASP: Security policy would not allow process: 1948, /User/USER/Library/Developer/Xcode/DerivedData/LockerRoom-eyzvsjkjmatcbndmhghzrtcwfqqf/Build/Products/Debug/LockerRoom.app/Contents/MacOS/LockerRoomDaemon

同时出现如下崩溃报告:

Incident Identifier: 47BFEBAE-8BE8-443C-8705-EC7FB7269879
CrashReporter Key:   E7C56EE2-21DE-F362-2A8E-B971E1F74B69
Hardware Model:      MacBookPro18,3
Process:             LockerRoomDaemon [1761]
Path:                /Users/USER/Library/Developer/Xcode/DerivedData/LockerRoom-eyzvsjkjmatcbndmhghzrtcwfqqf/Build/Products/Debug/LockerRoom.app/Contents/MacOS/LockerRoomDaemon
Identifier:          LockerRoomDaemon
Version:             ???
Code Type:           ARM-64 (Native)
Role:                Default
Parent Process:      launchd [1]
Coalition:           com.nsnolan.LockerRoomDaemon [1209]

Date/Time:           2024-07-27 23:01:47.0847 -0500
Launch Time:         2024-07-27 23:01:46.9770 -0500
OS Version:          macOS 14.2 (23C64)
Release Type:        User
Report Version:      104

Exception Type:  EXC_CRASH (SIGKILL (Code Signature Invalid))
Exception Codes: 0x0000000000000000, 0x0000000000000000
Termination Reason: CODESIGNING 4 Launch Constraint Violation

当我禁用SIP并使用临时签名时,daemon可正常启动并处理XPC消息。是什么原因导致AMFI检测到启动约束违规?

我认为macOS应用不需要配置描述文件,且Xcode界面似乎也阻止我配置。我还尝试过让daemon使用与应用相同的标识符签名(通过Xcode的“其他代码签名标志”设置),但问题仍未解决。

分析与解决

从日志和签名信息来看,导致AMFI启动约束违规的核心原因主要有以下几点:

1. Daemon标识符存在无效空格

查看daemon的签名输出,Identifier= com.nsnolan.LockerRoomDaemon里标识符前多了一个空格,这会导致AMFI验证时,签名的标识符与注册的服务标识符com.nsnolan.LockerRoomDaemon不匹配,直接触发约束违规。

2. Daemon未绑定Info.plist且缺少必要权限声明

system域的launch daemon必须绑定自己的Info.plist,用来声明服务标识、版本等核心信息,但你的daemon签名显示Info.plist=not bound,同时也没有启用Hardened Runtime权限:

  • SIP启用时,system级服务要求必须开启Hardened Runtime,Debug环境下需勾选Debugging Tools权限,否则AMFI会拦截启动
  • 父App需要拥有com.apple.security.sm.system-service权限,才能注册system域的daemon

3. System域服务的启动约束限制

通过ServiceManagement API注册的system域daemon,在SIP启用状态下有严格的验证逻辑:

  • 只能由已签名且符合Hardened Runtime要求的父App触发启动
  • daemon的签名必须与父App使用同一团队证书,且权限配置完整

具体解决步骤:

  • 修正标识符空格问题:在Xcode的daemon目标中,检查Bundle Identifier字段,确保没有多余空格,重新构建签名后,用codesign -d -i /path/to/daemon验证标识符完全匹配com.nsnolan.LockerRoomDaemon
  • 为daemon添加并绑定Info.plist:给daemon目标创建Info.plist,填写CFBundleIdentifier、CFBundleVersion等必填字段,在Xcode的Build Settings中指定Info.plist File的正确路径,确保签名时绑定该文件
  • 启用Hardened Runtime并配置权限:给父App和daemon都开启Hardened Runtime,Debug环境下勾选Debugging Tools权限;父App需添加com.apple.security.sm.system-service权限,允许其注册system级服务
  • 验证签名一致性:确保daemon和父App使用同一团队的开发者证书签名,daemon的签名需包含XPC通信必要的权限(如使用应用组则添加com.apple.security.application-groups)

内容的提问来源于stack exchange,提问作者NSNolan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 07:19:50