C – How to create a Unix domain socket with specific access rights

How to create a Unix domain socket with specific access rights… here is a solution to the problem.

How to create a Unix domain socket with specific access rights

I

have a situation where I intend to communicate with the service through the command interface provided by a UNIX domain socket on the file system. I was able to successfully send commands to it, but for a while I was confused as to why I couldn’t get any response to my query.

It turns out that the service does not have sufficient permissions to write to the address that I (or the operating system) gave it. However, I realized that if I explicitly bind (bind) to an address on the filesystem, then I can adjust file permissions by utilizing chmod.

Similar to:

int mySocket;
struct sockaddr_un local_addr; 

mySocket = socket(AF_UNIX, SOCK_DGRAM, 0);
local_addr.sun_family = AF_UNIX;
snprintf(local_addr.sun_path, 108  "/path/to/mySocket");

bind(mySocket, (struct sockaddr *) &local_addr, sizeof(struct sockaddr_un));
chmod("/path/to/mySocket", 777);

That is, without the final chmod step, the service will not be able to write to mySocket because it does not have proper write permissions. Obviously, without explicitly binding to a specific address, this is a harder problem to spot, as the underlying OS will implicitly generate this socket for the user – but it still exists and will still have the same access issues.

So, my question is about this last step. Is there a way to allow the OS to implicitly generate a socket for my endpoint (i.e. the address to which the service will respond) but request that it be granted certain permissions?


Explain

The reason this problem becomes problematic is that other parts of the program need to be executed as root. So when I try connect/send to a background service as root, the OS will implicitly create an address to which the reply will be directed. However, this has led to an issue with my socket file, whether implicitly or created with bind, which will have permissions like srw- --- --- , so another endpoint can only reply if they also elevate themselves.

So if I bind first and then chmod permissions, the problem goes away, as shown above.

Solution

Is there a way to allow the OS to implicitly generate the socket for my endpoint (i.e. the address to which the service will respond) but request that it be given certain permissions?

I solved this problem by calling umask()

twice

Pseudocode:

current_mask = umask(umask_to_be_used_on_afunix_socket_file_system_entry_creation);
bind afunix socket here
umask(current_umask);

Related Problems and Solutions