Why Do Permissions Matter for Sockets?
A UNIX domain socket appears as a special file in the file system when you call bind(). Like any file, it has an owner, a group, and permission bits. These permissions control which processes can connect to or send data to the socket.
This is a powerful access-control mechanism: you can restrict your socket so that only processes owned by the same user (or same group) can talk to it, without writing any authentication code yourself.
To connect() to a UNIX domain stream socket, the connecting process needs write permission on the socket file.
To sendto() a UNIX domain datagram socket, the sending process needs write permission on the socket file.
/tmp/mysocket, execute permission on /tmp is required.When bind() creates the socket file, the permissions are set based on the process’s current umask. By default (umask = 0), all permissions are granted to owner, group, and other:
The leading s in srwxrwxrwx indicates it is a socket file, not a regular file or directory. You can verify with ls -la.
To limit which users can connect, call umask() before bind() to disable certain permission bits. After bind(), restore the original umask.
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
struct sockaddr_un addr;
int sfd;
mode_t old_umask;
sfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sfd == -1) { perror("socket"); exit(1); }
remove("/tmp/restricted_sock");
memset(&addr, 0, sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, "/tmp/restricted_sock",
sizeof(addr.sun_path) - 1);
/*
* Set umask to 0077 before bind().
* This blocks write (and execute) for group and other.
* Only the owning user can connect.
*/
old_umask = umask(0077);
if (bind(sfd, (struct sockaddr *) &addr,
sizeof(struct sockaddr_un)) == -1) {
perror("bind"); exit(1);
}
/* Restore original umask */
umask(old_umask);
/*
* Now the socket file looks like:
* srw------- (only owner can write = only owner can connect)
*/
printf("Socket created with restricted permissions.\n");
/* ... listen(), accept(), etc. ... */
exit(EXIT_SUCCESS);
}
โ owner connect
โ group connect
โ others connect
โ owner connect
โ group blocked
โ others blocked
The SUSv3 standard allows implementations to ignore the permissions on a socket file. Some UNIX systems do exactly that โ they let any process connect regardless of the file permissions.
Using socket file permissions to control access may not work on all UNIX systems.
Use permissions on the hosting directory to restrict access. If the directory is only accessible to the intended user, others cannot even find the socket file.
/* Portable approach: restrict the directory, not just the socket file */
/* Create a private directory only the owner can enter */
mkdir("/var/run/myapp", 0700); /* rwx------ for owner only */
/* Place the socket inside */
strncpy(addr.sun_path, "/var/run/myapp/mysocket",
sizeof(addr.sun_path) - 1);
/* No umask needed: directory protection is portable */
bind(sfd, (struct sockaddr *) &addr, sizeof(addr));
A: Write permission on the socket file is required to call connect() to a UNIX domain stream socket. This applies to both stream and datagram sockets (for sendto()).
A: Call umask(0077) before bind() to block group and other write permissions. Restore the original umask after bind(). This results in socket file permissions of srw-------, allowing only the file’s owner to connect.
A: No. SUSv3 permits implementations to ignore socket file permissions. Some systems allow any process to connect regardless of the permissions. For portable access control, use directory permissions: place the socket in a directory accessible only to authorised users. This approach works on all UNIX implementations.
A: Every directory in the socket’s path requires execute (search) permission. For example, for /var/run/myapp/mysock, the process must have execute permission on /, /var, /var/run, and /var/run/myapp.
A: The s at the beginning of the permissions string indicates that the file is a socket (a special file type). It is similar to d for directory, l for symlink, or - for regular file.
A: The sendto() call will fail with errno set to EACCES (Permission denied), on systems that enforce socket file permissions. On systems that ignore socket permissions (as permitted by SUSv3), the call may succeed.
Next: Creating a Connected Socket Pair with socketpair()
