Я работаю над приложением, которое использует сокет домена Unix для IPC. Насколько я знаю, распространенный способ — поместить файл сокета внутрь /var/run
. Я работаю с Ubuntu 18.04 и вижу, что var/run
это символическая ссылка для /run
. К сожалению, папка доступна root
только для:
ls -Al /
drwxr-xr-x 27 root root 800 Apr 12 17:39 run
Таким образом, доступ на запись в эту папку есть только у пользователя root, что делает невозможным использование доменных сокетов Unix для обычных пользователей.
Во-первых, я не могу понять, почему? И как использовать сокеты домена Unix для не-root пользователей? Я могу использовать домашнюю папку, конечно, но я предпочитаю использовать какой-то правильный и общепринятый метод.
решение1
Нет ничего плохого в создании сокета в dotfile или dotdir в домашнем каталоге пользователя, если пользователь не является каким-то особым системным пользователем. Единственная проблема будет в домашнем каталоге, общем для нескольких машин через nfs, но это можно легко обойти, включив имя хоста в имя сокета.
В Linux/Ubuntu вы также можете использовать"абстрактный"Сокеты домена Unix, которые не используют никаких путей или инодов в файловой системе. Абстрактные сокеты Unix — это те, адрес/путь которых начинается с байта NUL:
абстрактный: абстрактный адрес сокета отличается (от имени пути сокета) тем, что
sun_path[0]
представляет собой нулевой байт (\0
).Адрес сокета в этом пространстве имен задается дополнительными байтами,
sun_path
которые покрываются указанной длиной структуры адреса. (Нулевые байты в имени не имеют особого значения.) Имя не связано с путями файловой системы. Когда возвращается адрес абстрактного сокета, возвращаемоеaddrlen
большеsizeof(sa_family_t)
(т. е. больше 2), а имя сокета содержится в первых(addrlen - sizeof(sa_family_t))
байтахsun_path
.
При отображении или вводе пользователем байты NUL в абстрактном адресе сокета Unix обычно заменяются на s. Многие программы делают это ужасно неправильно, поскольку они никак @
не экранируют обычные s и/или предполагают, что только первый байт может быть NUL.@
В отличие от обычных путей сокетов Unix, абстрактные имена сокетов Unix имеют другую семантику, поскольку к ним может привязаться кто угодно (если имя еще не занято), и к ним может подключиться кто угодно.
Вместо того чтобы полагаться на разрешение файла/каталога для ограничения того, кто может подключаться к вашему сокету, и предполагать, что, например, только пользователь root может создавать сокеты внутри некоторого каталога, вам следует проверить учетные данные однорангового узла getsockopt(SO_PEERCRED)
(чтобы получить uid/pid того, кто подключился или связал одноранговый узел) или SCM_CREDENTIALS
вспомогательное сообщение (чтобы получить uid/pid того, кто отправил сообщение через сокет).
Это (замена обычных проверок прав доступа к файлам) также является единственным разумным использованием SO_PEERCRED
/ SCM_CREDENTIALS
IMHO.
решение2
Ваш сокет домена unix не должен напрямую входить в /run
, вам нужно создать папку внутри /run
, например, /run/my-ipc
с соответствующими правами для вашего пользователя, а затем писать в эту папку.
Папка должна быть пересозданной при загрузке. Принятый ответ дляэтот вопрособъясняет несколько альтернатив.