Unix Domain Sockets Not Accessable Across Users

UNIX domain sockets not accessable across users?

With some assistance from the ZMQ mailing list, I have made a work around. It's ugly, but seems to work consistently.

I had to make a subdirectory under /tmp and chmod 777 it. The server now creates the socket in that new folder. It also programmatically chmod 777 the socket. Now, as long as the server is run as root, any user can run a client and talk to the server.

I don't know why UNIX domain socket behave this way, but it sure is annoying.

why my unix domain socket can't work

You should be sending to /var/run/lsvr.sock not to /var/run/lcli.sock.

Also you don't have to bind in client so comment it out from client:

/*    if(bind(CliFD, (struct sockaddr *)&cliaddr, sizeof(cliaddr)))
mpExit("cli bind");*/

can i access a unix domain socket on a remote machine?

Unix domain sockets are meant for inter-process communication within the same host machine. Data sent through these sockets are handled entirely inside the kernel. For communication between processes in different machines, you should use network sockets.

How do Unix Domain Sockets differentiate between multiple clients?

If you create a PF_UNIX socket of type SOCK_STREAM, and accept connections on it, then each time you accept a connection, you get a new file descriptor (as the return value of the accept system call). This file descriptor reads data from and writes data to a file descriptor in the client process. Thus it works just like a TCP/IP connection.

There's no “unix domain protocol format”. There doesn't need to be, because a Unix-domain socket can't be connected to a peer over a network connection. In the kernel, the file descriptor representing your end of a SOCK_STREAM Unix-domain socket points to a data structure that tells the kernel which file descriptor is at the other end of the connection. When you write data to your file descriptor, the kernel looks up the file descriptor at the other end of the connection and appends the data to that other file descriptor's read buffer. The kernel doesn't need to put your data inside a packet with a header describing its destination.

For a SOCK_DGRAM socket, you have to tell the kernel the path of the socket that should receive your data, and it uses that to look up the file descriptor for that receiving socket.

If you bind a path to your client socket before you connect to the server socket (or before you send data if you're using SOCK_DGRAM), then the server process can get that path using getpeername (for SOCK_STREAM). For a SOCK_DGRAM, the receiving side can use recvfrom to get the path of the sending socket.

If you don't bind a path, then the receiving process can't get an id that uniquely identifies the peer. At least, not on the Linux kernel I'm running (2.6.18-238.19.1.el5).

How to create a Unix-domain socket with specific access permissions

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 very problem once using two calls to umask().

Pseudo code:

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

Does data passed across a unix domain socket cross the kernel boundary?

Of course Unix sockets go via the kernel, but your question is founded on a misconception. You wouldn't see a benefit from introducing another copy step via splice.

Calling open() on a Unix domain socket failed with error No such device or address

The /tmp/pipe1 is not a pipe file. It's a socket file. That's what the leading s means in srwxr-xr-x.

And Bash's redirection like > does not support socket files. You need to use socket API to open the file.


With strace (e.g. strace bash -c 'echo > /tmp/sockfile') we can see:

...
openat(AT_FDCWD, "/tmp/sockfile", ...) = -1 ENXIO (No such device or address)
...

So the error code is ENXIO whose corresponding error message is No such device or address. Bash is just calling standard C API (like strerror) to print the error.


Exampe code for client side:

int
sock_connect(char * sockpath)
{
int sock_fd;
struct sockaddr_un srv_addr = { 0 };

sock_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
if (sock_fd < 0) {
return -1;
}

srv_addr.sun_family = AF_LOCAL;
snprintf(srv_addr.sun_path, sizeof(srv_addr.sun_path), "%s", sockpath);
if (connect(sock_fd, (struct sockaddr *) & srv_addr, sizeof(srv_addr)) < 0) {
return -1;
}

return sock_fd;
}


Related Topics



Leave a reply



Submit