Расширение приложения Mac, вызывающее connect на сокете Unix, получает EPERM (песочница?)
Я работаю над большим Mac-приложением, которое разбито на множество компонентов в разных процессах. Одним из таких компонентов является Safari Extension Companion[1], который является своего рода "расширением приложения", которое позволяет расширению на основе JavaScript взаимодействовать с собственным кодом (это требуется для безопасного IPC между нашими компонентами). Канал IPC является доменным сокетом Unix в пользовательском ~/Library/Application Support/<APPNAME>/
каталог. По устаревшим причинам сервер сокетов Unix говорит по HTTP, а клиентская библиотека для него использует пользовательский URLProtocol
В случае, если это имеет значение.
Это прекрасно работает для всех других наших компонентов, но ни один из них не работает в песочнице [2]. Тем не менее, шаблон XCode для компаньона расширения создал песочницу, и, пока компаньон загружается, если песочница находится, она, кажется, требует песочницу. Я пробовал настройку com.apple.security.app-sandbox
в false
в файле разрешений или при удалении файла разрешений (и всех ссылок на него) оба, как представляется, вообще не позволяют Safari загружать компаньон (он все равно работает как собственный двоичный файл, если вызывается напрямую, но Safari, очевидно, не будет его трогать),
Я добавил исключения в изолированную программную среду, чтобы разрешить ей доступ к соответствующему каталогу и только к сокету IPC; но этого, кажется, недостаточно. Ошибка при попытке открыть сокет EPERM
(Операция не разрешена), которая на самом деле не объясняет проблему. После добавления исключений к разрешениям и исправления путей, такие вещи, как файл журнала (также под "реальным" ~/Library/
) теперь пишите как положено.
Эта ошибка происходит на connect
вызовите сокет (он возвращает -1, указывая на ошибку, и errno
это 1 (EPERM
)) так что на самом деле никогда не делается попытка записи или чтения из сокета. Это кажется мне очень странным, так как - согласно Руководству по дизайну Apple Sandbox -
Доменные сокеты 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] Использование Companion Extension, а не расширения Safari App с собственным кодом, поскольку фоновая / глобальная логика довольно сложна, но в настоящее время в основном идентична во всех основных браузерах; переписывание его на нативном коде было бы серьезной единовременной задачей, а также постоянным бременем обслуживания. Я также подозреваю, что это не поможет с моей проблемой.
[2] Два основных не могут быть помещены в "песочницу", так как они требуют доступа ко всей файловой системе. Приложение не распространяется через App Store, поэтому отсутствие песочницы не создает проблем с соответствием. Я бы хотел включить песочницу для безопасности, но это не практично.
1 ответ
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
). Временные права все еще там для доступа к таким вещам, как журналы и каталоги конфигурации. Сетевые права и права доступа к выбранным пользователем файлам не были нужны и были удалены.