Mac 应用程序扩展调用 Unix 套接字上的连接获取 EPERM(沙盒?



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

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

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

此错误发生在套接字的connect调用上(它返回 -1,表示错误,errno为 1 (EPERM)),因此实际上从未尝试写入或读取套接字。这对我来说似乎很奇怪,因为 - 根据 Apple 沙盒设计指南 -

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 扩展伴侣在不对其进行沙盒处理的情况下工作?如果没有,如何允许同伴使用 IPC 套接字?

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


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

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


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

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

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

找到了解决方案。转我们的Apple文档是错误的:Unix域套接字无法通过com.apple.security.temporary-exception.files.home-relative-path.read-write权利访问,即使普通文件可以访问。这就是导致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中。临时权利仍然存在,可以访问日志和配置目录等内容。不需要网络授权和用户选择的文件授权,并且已被删除。

相关内容

  • 没有找到相关文章

最新更新