3

我正在开发一个大型 Mac 应用程序,该应用程序在许多不同进程中的许多组件中拆分。其中一个组件是 Safari Extension Companion[1],它是一种“应用程序扩展”,允许基于 JavaScript 的扩展与本机代码对话(这是我们组件之间安全 IPC 所必需的)。IPC 通道是用户~/Library/Application Support/<APPNAME>/目录中的一个 Unix 域套接字。由于遗留原因,Unix 套接字服务器使用 HTTP 并且客户端库使用自定义URLProtocol的,以防万一。

这适用于我们所有其他组件,但它们都没有在沙箱中运行[2]。但是,扩展伴侣的 Xcode 模板创建了一个沙箱,如果沙箱加载了伴侣,它似乎需要沙箱。我尝试在权利文件中设置com.apple.security.app-sandboxfalse或删除权利文件(以及对它的所有引用),两者似乎都阻止了 Safari 加载伴侣(如果直接调用它仍然作为自己的二进制文件运行,但 Safari 显然不会不要碰它)。

我在沙箱中添加了例外,以允许它直接访问相关目录,以及直接访问 IPC 套接字;但这似乎还不够。尝试打开套接字时遇到的错误是EPERM(不允许操作),这并不能真正解释问题。在将例外添加到权利并修复路径之后,日志文件(也在 "real" 下~/Library/)之类的内容现在按预期写入。

这个错误发生在对connect套接字的调用上(它返回-1,表示一个错误,并且errno是1(EPERM)),所以实际上从来没有尝试写入或读取套接字。这对我来说似乎很奇怪,因为 - 根据Apple Sandbox Design Guide -

UNIX 域套接字很简单;它们就像任何其他文件一样工作

关于沙盒异常。

权利文件(使用此处的答案从自动生成的模板修改:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.security.app-sandbox</key>
    <true/>
    <key>com.apple.security.files.user-selected.read-only</key>
    <true/>
    <key>com.apple.security.network.client</key>
    <true/>
    <key>com.apple.security.network.server</key>
    <true/>
    <key>com.apple.security.temporary-exception.files.home-relative-path.read-write</key>
    <array>
        <string>/Library/Application Support/{APPNAME}/</string>
        <string>/Library/Application Support/{APPNAME}/ipc_socket</string>
        <string>/Library/Logs/{APPNAME}/</string>
    </array>
</dict>
</plist>

有没有办法让 Safari Extension Companion 完全不用沙箱工作?如果没有,我如何允许同伴使用 IPC 套接字?

或者,有没有办法在扩展伴侣中使用 UNIX 套接字(如果问题不在于沙箱本身)?


*编辑:此问题已被编辑为先前的问题 -ENOENT调用时(未找到文件)connect- 在得到任何评论或答案之前已解决。这是由于sockaddr_un完整的域套接字路径太短,并且通过使用套接字的真实路径而不是通过沙盒版本的(非常长的)路径Library/Application Support和在那里种植的符号链接来解决。但是,新问题似乎在同一个地方,也可能是由于沙盒。

编辑 2:更新了权利以包括网络客户端(和服务器,为了很好的衡量标准)。虽然 Unix 套接字不是网络套接字,但它是一个失败的网络 API,所以我认为它可能会有所帮助。不过没有区别;还是继续EPERM打电话吧connect


[1] 使用 Extension Companion 而不是原生代码 Safari App Extension,因为背景/全局逻辑相当复杂,但目前在所有主要浏览器中基本相同;用本机代码重写它将是一项重大的一次性任务,也是一项持续的维护负担。我也怀疑这对我遇到的问题没有帮助。

[2] 两个主要的不能被沙盒化,因为它们需要访问整个文件系统。该应用程序不是通过 App Store 分发的,因此缺少沙盒不会带来合规性问题。为了安全起见,我想启用沙盒,但这不切实际。

4

1 回答 1

7

TL;DR:Unix 套接字必须在沙盒容器或组容器中!

找到了解决方案。转我们 Apple 的文档是错误的:无法通过com.apple.security.temporary-exception.files.home-relative-path.read-write权利访问 Unix 域套接字,即使普通文件可以。这就是导致EPERM错误的原因。

套接字必须在沙箱的容器中,或者在沙箱有权访问的组容器中。鉴于长度限制sockaddr_un.sun_path以及我们的(长)包名称包含在特定于沙箱的容器路径中的事实,我决定创建一个组容器。这也将使将来对其他组件进行沙箱化变得更加容易。权利文件的最终版本如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.security.app-sandbox</key>
    <true/>
    <key>com.apple.security.application-groups</key>
    <array>
        <string>{REVERSED.COMPANY.DOMAIN}</string>
    </array>
    <key>com.apple.security.temporary-exception.files.home-relative-path.read-write</key>
    <array>
        <string>/Library/Application Support/{APPNAME}/</string>
        <string>/Library/Logs/{APPNAME}/</string>
    </array>
</dict>
</plist>

套接字放置在组容器 ( ~/Library/Group Containers/{REVERSED.COMPANY.DOMAIN}/ipc_socket) 中。临时权利仍然在那里,可以访问日志和配置目录等内容。不需要网络权利和用户选择的文件权利,因此已将其删除。

于 2017-07-25T18:44:08.613 回答