Identify Program That Connects to a Unix Domain Socket

Identify program that connects to a Unix Domain Socket

Yes, this is possible on Linux, but it won't be very portable. It's achieved using what is called "ancillary data" with sendmsg / recvmsg.

  • Use SO_PASSCRED with setsockopt
  • Use SCM_CREDENTIALS and the struct ucred structure

This structure is defined in Linux:

struct ucred {
pid_t pid; /* process ID of the sending process */
uid_t uid; /* user ID of the sending process */
gid_t gid; /* group ID of the sending process */
};

Note you have to fill these in your msghdr.control, and the kernel will check if they're correct.

The main portability hindrance is that this structure differs on other Unixes - for example on FreeBSD it's:

struct cmsgcred {
pid_t cmcred_pid; /* PID of sending process */
uid_t cmcred_uid; /* real UID of sending process */
uid_t cmcred_euid; /* effective UID of sending process */
gid_t cmcred_gid; /* real GID of sending process */
short cmcred_ngroups; /* number or groups */
gid_t cmcred_groups[CMGROUP_MAX]; /* groups */
};

Identify other end of a unix domain socket connection

Update: It's been possible to to do this using actual interfaces for a while now. Starting with Linux 3.3, the UNIX_DIAG feature provides a netlink-based API for this information, and lsof 4.89 and later support it. See https://unix.stackexchange.com/a/190606/1820 for more information.

Find PID of the connected Unix Domain Socket

Based on this Golang issue implementing the same thing, you can do

sock, addr = server.accept()
other_pid = sock.getsockopt(0, 2)

where 0 corresponds to SOL_LOCAL and 2 to LOCAL_PEERPID.

I just tried it out – works fine on my Mac.

how do I find out what program's on the other end of a local socket?

ss -p

will tell. (Provided the socket is not owned by the kernel itself.)

Can a client determine whether the server has accept()'d a unix socket?

Looks like the answer to this is "no"; the kernel offers no way to get at this info.

(change the protocol isn't an answer, since I was debugging a pre-existing unchangeable protocol)

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