UNIX Domain Socket Permissions Linux System Programming

 

UNIX Domain Socket Permissions
Chapter 57.4 โ€” Linux System Programming | EmbeddedPathashala
๐Ÿ”’ File Permissions
๐Ÿ‘ค umask()
๐Ÿ“‚ Directory Access

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.

๐Ÿ”“ The Two Permission Rules

๐Ÿ”— Stream Socket (SOCK_STREAM)

To connect() to a UNIX domain stream socket, the connecting process needs write permission on the socket file.

connect() requires: w on socket file
๐Ÿ“ค Datagram Socket (SOCK_DGRAM)

To sendto() a UNIX domain datagram socket, the sending process needs write permission on the socket file.

sendto() requires: w on socket file
๐Ÿ“‚ Directory Permission: In addition to the socket file’s own permission, the process must also have execute (search) permission on every directory in the socket’s path. For example, to access /tmp/mysocket, execute permission on /tmp is required.

๐Ÿ“„ Default Permissions at Creation

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:

# Default socket file permissions
srwxrwxrwx 1 ravi ravi 0 Jun 13 10:00 /tmp/mysocket
# s = socket file type
# rwxrwxrwx = all permissions for owner/group/other

The leading s in srwxrwxrwx indicates it is a socket file, not a regular file or directory. You can verify with ls -la.

๐Ÿ”’ Restricting Access with umask()

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);
}

Without umask restriction:

srwxrwxrwx
โœ“ owner connect
โœ“ group connect
โœ“ others connect
With umask(0077):

srw——-
โœ“ owner connect
โœ— group blocked
โœ— others blocked

๐ŸŒŽ Portability Warning

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.

โš  Not Portable
Using socket file permissions to control access may not work on all UNIX systems.
โœ“ Portable Alternative
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));
๐Ÿ’ก Rule of Thumb: If you want portable access control, place the socket in a directory with tight permissions rather than relying solely on socket file permissions.

๐ŸŽ“ Interview Questions & Answers
Q1. What file permission is required to connect to a UNIX domain stream socket?

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()).

Q2. How do you create a UNIX domain socket that only the owning user can connect to?

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.

Q3. Are socket file permissions portable across all UNIX systems?

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.

Q4. What additional permission is needed beyond the socket file itself?

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.

Q5. What does the ‘s’ character mean in “srwxrwxrwx” when you run ls on a socket file?

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.

Q6. What happens if a process without write permission tries to send a datagram to a UNIX domain socket?

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.

Continue Learning

Next: Creating a Connected Socket Pair with socketpair()

Next: socketpair() โ†’ โ† Previous

Leave a Reply

Your email address will not be published. Required fields are marked *