Как создать Unix-домен Socket с определенными разрешениями в C?
У меня есть простой код, например:
sockaddr_un address;
address.sun_family = AF_UNIX;
strcpy(address.sun_path, path);
unlink(path);
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
bind(fd, (sockaddr*)(&address), sizeof(address));
listen(fd, 100);
Я хочу атомизировать создать файл Unix Domain Socket с определенными правами, например: 0777
. В руководстве ничего не говорится о разрешениях файлов сокетов в отношении umask
или что-то еще. Даже если umask
влияет на файл сокета, то это не атомный путь - в многопоточной программе.
Надеюсь, есть способ достичь моей цели, не используя синхронизацию вызовов umask()
.
Ответы
Ответ 1
Другим решением является создание каталога с требуемыми разрешениями, а затем создание сокета внутри него (пример кода без учета ошибок и переполнения буфера):
// Create a directory with the proper permissions
mkdir(path, 0700);
// Append the name of the socket
strcat(path, "/socket_name");
// Create the socket normally
sockaddr_un address;
address.sun_family = AF_UNIX;
strcpy(address.sun_path, path);
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
bind(fd, (sockaddr*)(&address), sizeof(address));
listen(fd, 100);
Ответ 2
Мне посчастливилось использовать chmod() (NOT fchmod), используя имя файла для сокета домена unix после вызова socket(), bind(), но перед вызовом listen().
int return_value;
const char *sock_path;
struct sockaddr_un local;
sock_path = "/tmp/mysocket";
sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sockfd == -1)
{
perror("socket");
exit(-1);
}
local.sun_family = AF_UNIX;
strcpy(local.sun_path, sock_path);
unlink(local.sun_path);
len = strlen(local.sun_path) + sizeof(local.sun_family);
bind(sockfd, (struct sockaddr *)&local, len);
chmod(sock_path, 0777);
retval = listen(sockfd, BACKLOG);
if (retval == -1)
{
perror("listen");
exit(-1);
}
.,,
Ответ 3
Викинг, использование umask и передача назад fd - единственный переносимый способ, о котором я могу думать. Наличие каталога для сокета лучше в любом случае, например, никто не может удалить сокет, если каталог не имеет правильных разрешений, а создание директив может выполняться атомарно.
Большая проблема заключается в том, что использование разрешений не переносимо - многие стеки сокетов, созданные BSD, просто игнорируют разрешения на включение каталогов и/или самого сокета.
В системах GNU/Linux вы можете сделать это, вызвав fchmod на сокете fd после socket() и перед bind()