Reputation: 14452
I have a simple code, like:
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);
I want to atomically create the Unix Domain Socket file with a specific permissions, say: 0777
. The manual doesn't say anything about socket file permissions with regard to umask
or whatever. Even, if the umask
does affect the socket file, then it's not an atomic way - in multi-threaded program.
I hope, there is a way to achieve my goal without using synchronization of umask()
calls.
Upvotes: 32
Views: 34361
Reputation: 116
Forking, using umask
and passing back the fd
is the only portable way I can think of. Having a directory for the socket is better in any case, for example nobody can delete the socket if the directory doesn't have the proper permissions, and creating directories can be done atomically.
The bigger problem is that relying on permissions is not portable - many BSD-derived socket stacks simply ignore the permissions of enclosing directories and/or the socket itself.
On GNU/Linux systems, you can do it by calling fchmod()
on the socket fd
after socket()
and before bind()
.
Upvotes: 8
Reputation: 331
I had the best luck using chmod()
(NOT fchmod()
) using the file name for the unix domain socket after calling socket()
, bind()
, but, before calling 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);
}
. . . . .
Upvotes: 17
Reputation: 3885
Another solution is to create a directory with the desired permissions, and then create the socket inside it (example code without any regard for error checking and buffer overflows):
// 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);
Upvotes: 23