Search code examples
socketsfile-permissionsunix-socket

How to securely set the group ownership of a unix domain socket?


I want to create a Unix domain socket which is restricted to a particular group. So what I'd ideally do is (ignoring error checking) something like:

// Set the "address" (ie filesystem path)
struct sockaddr_un addr;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, "./my.sock");

int fd = socket(AF_UNIX, SOCK_DGRAM, 0);  // create the socket

// Set the group owner and permissions
fchmod(fd, 0770); // This seems to succeed
fchown(fd, -1, wanted_group_id);  // Silently fails

// Create the filesystem entry
bind(fd, (struct sockaddr *)&addr, sizeof(addr));

However, fchown on a socket has no effect, so it seems that chown afterwards is the only way to set the group. I want to avoid having the socket temporarily accessible to processes which shouldn't be permitted to access it.

The best idea I have is:

int fd = socket(...);
fchmod(fd, 0700);  // Remove group permissions
bind(fd, ...);     // Create fs entry
chown("./my.sock", -1, wanted_group_id); // set the correct group owner
fchmod(fd, 0770);  // And restore group permissions

Surely this is a common thing to want to do with Unix sockets, and there's a canonical way of achieving this, but I haven't found any clear answers.

I'm only really interested in Linux, but bonus points for something that only relies on POSIX.


Solution

  • The way to do this is to put the socket into a directory with the correct permissions. Directories can be created (or renamed into place) atomically, and once the directory is present the permissions on the socket itself are not very important. This also works on the Unixes where the permissions on the socket itself aren't always honoured.