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.
Is there a way to get the uid of the other end of a unix socket connection
The easiest way to check peer credentials is with SO_PEERCRED
.
To do this for socket sock
:
int len;
struct ucred ucred;
len = sizeof(struct ucred);
if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1)
// check errno
printf("Credentials from SO_PEERCRED: pid=%ld, euid=%ld, egid=%ld\n",
(long) ucred.pid, (long) ucred.uid, (long) ucred.gid);
SO_PEERCRED
Return the credentials of the foreign process connected to
this socket. This is possible only for connected AF_UNIX
stream sockets and AF_UNIX stream and datagram socket pairs
created using socketpair(2); see unix(7). The returned
credentials are those that were in effect at the time of the
call to connect(2) or socketpair(2). The argument is a ucred
structure; define the _GNU_SOURCE feature test macro to obtain
the definition of that structure from <sys/socket.h>. This
socket option is read-only.
From a tlpi example. PostgreSQL has a few variants for other unices.
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
withsetsockopt
- Use
SCM_CREDENTIALS
and thestruct 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 */
};
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.)
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
).
Is it possible to find which user is at the other end of a localhost TCP connection?
On Linux, /proc/net/tcp
contains information on the open TCP sockets on the system. For a connected socket, the entries look like this (the header is part of the file, other lines removed):
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
11: 0100007F:C9CB 0100007F:0016 01 00000000:00000000 00:00000000 00000000 1000 0 978132 ...
The second and third columns have the endpoints of the socket, and the uid
column has the effective UID of the process what created the socket. /proc/net/tcp6
is similar for IPv6. (The IP address there is 127.0.0.1, so the octets seem to be in reverse order.)
If you wanted to track the actual process(es) holding the socket, you'd need to go through all /proc/$PID/fd/$N
entries, and compare the inode numbers in the socket symlinks to the inode number mentioned in the tcp socket table. But you can only see the file descriptors of your own processes, unless you're the superuser.
Related Topics
Bash Script Read All the Files in Directory
How to Fix Permission Denied for .Git/ Directory When Performing Git Push
What Does Double Slash // in 'Cd //' Mean in Linux
Allocate Writable Memory in the .Text Section
Use Grep to Find Content in Files and Move Them If They Match
How to Automatically Start a Node.Js Application in Amazon Linux Ami on Aws
Detecting Keyboard, Mouse Activity in Linux
Identifying Received Signal Name in Bash
Has Anyone Been Able to Create a Hybrid of Pe Coff and Elf
Why Does C99 Complain About Storage Sizes
Using Linux How to Pass the Contents of a File as a Parameter to an Executable
Check If Rsync Command Ran Successful
How to Tell If a File Is Older Than 30 Minutes from /Bin/Sh
Differencebetween './Example.Sh' and 'Sh Example.Sh'
When to Use Kernel Threads VS Workqueues in the Linux Kernel
Managing a User Password for Linux in Puppet
How to Run a Command in a Chroot Jail Not as Root and Without Sudo