macos - Mac 应用程序扩展在 Unix 套接字上调用 connect 获取 EPERM(沙盒?)

标签 macos appstore-sandbox unix-socket safari-app-extension

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

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

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

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

UNIX domain sockets are straightforward; they work just like any other file

关于沙盒异常。

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

<?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 的(非常长的)路径来解决和在那里种植的符号链接(symbolic link)。但是,新问题似乎在同一个地方,也可能是由于沙盒造成的。

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


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

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

最佳答案

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)。临时权利仍然在那里,可以访问日志和配置目录等内容。不需要网络授权和用户选择的文件授权,已被删除。

关于macos - Mac 应用程序扩展在 Unix 套接字上调用 connect 获取 EPERM(沙盒?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45243969/

相关文章:

macos - WKWebView 进程在没有沙箱授权的情况下终止

sockets - TCP 环回连接与 Unix 域套接字性能

c - 为什么程序运行在if((hptr = gethostbyname(buffer)) == NULL)时就崩溃了

c - 如何让用 C 编写的程序在终端或命令提示符中执行命令?

objective-c - 仅在 mac 中以编程方式截取应用程序窗口的屏幕截图

swift - Finder 同步扩展无法从桌面读取/写入文件

c - 为什么 UNIX 域数据报套接字的 recvfrom() 返回无效参数?

c++ - Apple C++ LLVM 编译器 4.x 和 UNICODE : when needed? UNICODE 是默认编译器字符集吗?使您的代码同时编译 ANSI 和 UNICODE 版本

macos - PlistBuddy 默默地失败了——bug?

php - 验证 App Store 收据时出现无效的 Drm 参数异常