Подтвердить что ты не робот

Как создать 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().

4b9b3361

Ответ 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()