Linux socket to process

Find original owning process of a Linux socket

In Linux and other UNIX-like operating systems, it is possible for two (or more) processes to share an Internet socket. Assuming there is no parent-child relationship between the processes, is there any way to tell what process originally created a socket? Clarification: I need to determine this from «outside» the processes using the /proc filesystem or similar. I can’t modify the code of the processes. I can already tell what processes are sharing sockets by reading /proc//fd , but that doesn’t tell me what process originally created them.

4 Answers 4

You can use netstat for this. You should look in the columns ‘Local Address’ and ‘PID/Program name’.

xxx@xxx:~$ netstat -tulpen (Not all processes could be identified, non-owned process info will not be shown, you would have to be root to see it all.) Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State User Inode PID/Program name tcp 0 0 127.0.0.1:4005 0.0.0.0:* LISTEN 1000 68449 7559/sbcl tcp 0 0 0.0.0.0:6000 0.0.0.0:* LISTEN 0 3938 - tcp6 0 0 . 6000 . * LISTEN 0 3937 - udp 0 0 0.0.0.0:68 0.0.0.0:* 0 4528 - 

Good answer with added information: It does work though I believe -a is unnecessary as results seem the same with and without -a, but, on some Linux, it appears ‘lsof’ is largely neutered and requires elevated permissions to find this information. For example, I wanted to know the PID of /tmp/ssh-W1Tl4i8HiftZ/agent.21283, but ‘lsof -Ua /tmp/ssh-W1Tl4i8HiftZ/agent.21283’ shows nothing at all — not even an error message. On the other hand, ‘sudo lsof -Ua /tmp/ssh-W1Tl4i8HiftZ/agent.21283’ was very revealing and did show a PID. Sadly, sudo or elevated permissions are not viable for many tasks.

You can likely find the shared sockets by parsing /proc/net/tcp (and similar «files» for other protocols). There’s some docs on /proc/net/tcp here.

You would need to find the socket (perhaps by its IP addresses/port numbers ?) and parse out the inode number. Once you have the inode, you can search through all of /proc/*/fd/* , calling stat for every link and inspect the st_ino member of struct stat until you find a match.

The inode number should match between the 2 processes, so when you’ve gone through all /proc/*/fd/* you should have found them both.

If what you do know is the process id and socket fd of the first, you might not need to go through /proc/net/tcp, all you need to do is stat the /proc//fd/ and search the rest of /proc/*/fd/* for a matching inode. You’d need /proc/net/tcp if you want to fetch the ip addresses/port number though — which you can find if you know the inode number

Maybe I didn’t explain myself well. I already know how to find out which processes are sharing sockets. I do that using exactly the method you described. But this doesn’t help me determine which process owned the socket originally. Perhaps I need to make a guess based on the age of each process.

Читайте также:  Linux server security hardening

It would be very helpful if you updated your question to state what you are looking for, and that you are doing this from outside any of the programs involved. There is however no direct information on the original owner or creator anywhere. The closest thing you will get is calling lstat on the links in /proc/pid/fd/fd and guess that the oldest timestamp(ctime likely) was the original creator.

@Rob H You cannot figure out what process originally created a socket, there is no information about that anywhere in the OS. You can only figure out which processes that have a reference(file descriptor) to a socket right now.

For purposes creating a test case, consider a situation where multiple ssh-agent processes are running and have open sockets. I.e. A user runs ssh-agent multiple times and loses the socket/PID information given when the agent started:

$ find /tmp -path "*ssh*agent*" 2>/dev/null /tmp/ssh-0XemJ4YlRtVI/agent.14405 /tmp/ssh-W1Tl4i8HiftZ/agent.21283 /tmp/ssh-w4fyViMab8wr/agent.10966 

Later, the user wants to programmatically determine the PID owner of a particular ssh-agent socket (i.e. /tmp/ssh-W1Tl4i8HiftZ/agent.21283):

$ stat /tmp/ssh-W1Tl4i8HiftZ/agent.21283 File: '/tmp/ssh-W1Tl4i8HiftZ/agent.21283' Size: 0 Blocks: 0 IO Block: 4096 socket Device: 805h/2053d Inode: 113 Links: 1 Access: (0600/srw-------) Uid: ( 4000/ myname) Gid: ( 4500/ mygrp) Access: 2018-03-07 21:23:08.373138728 -0600 Modify: 2018-03-07 20:49:43.638291884 -0600 Change: 2018-03-07 20:49:43.638291884 -0600 Birth: - 

In this case, because ssh-agent named its socket nicely as a human onlooker can guess that the socket belongs to PID 21284, because the socket name contains a numeric component that is one-off from a PID identified with ps :

$ ps -ef | grep ssh-agent myname 10967 1 0 16:54 ? 00:00:00 ssh-agent myname 14406 1 0 20:35 ? 00:00:00 ssh-agent myname 21284 1 0 20:49 ? 00:00:00 ssh-agent 

It seems highly unwise to make any assumption that the PIDs will be so reliable as to always only be off by one, but also, one might suppose that not all socket creators will name the sockets so nicely.

@Cypher’s answer points to a straightforward solution to the problem of identifying the PID of the socket owner, but is incomplete as lsof actually can only identify this PID with elevated permissions. Without elevated permissions, no results are forthcoming:

$ lsof /tmp/ssh-W1Tl4i8HiftZ/agent.21283 $ 

With elevated permissions, however, the PID is identified:

$ sudo lsof /tmp/ssh-W1Tl4i8HiftZ/agent.21283 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME ssh-agent 21284 myname 3u unix 0xffff971aba04cc00 0t0 1785049 /tmp/ssh-W1Tl4i8HiftZ/agent.21283 type=STREAM 

In this case, the owner of the PID (myname) and socket was the one doing the query, so it seemed elevated permissions should not be needed. Furthermore, the task performing the query was not supposed to be able to elevate permissions, so I looked for another answer.

This led me to @whoplisp’s answer proposing netstat -tulpen as a solution to the OP’s problem. While it may have been effective for the OP, the command line is too restrictive to serve as a general purpose command and was completely ineffective in this case (even with elevated permissions).

$ sudo netstat -tulpen | grep -E -- '(agent.21283|ssh-agent)' $ 

netstat , however, can come close if a different command-line is used:

$ netstat -ap | grep -E -- '(agent.21283)' (Not all processes could be identified, non-owned process info will not be shown, you would have to be root to see it all.) unix 2 [ ACC ] STREAM LISTENING 1785049 - /tmp/ssh-W1Tl4i8HiftZ/agent.21283 

Sadly, here too, the PID is elusive without elevated permissions:

$ sudo netstat -ap | grep -E -- '(agent.21283|ssh-agent)' unix 2 [ ACC ] STREAM LISTENING 1765316 10967/ssh-agent /tmp/ssh-w4fyViMab8wr/agent.10966 unix 2 [ ACC ] STREAM LISTENING 1777450 14406/ssh-agent /tmp/ssh-0XemJ4YlRtVI/agent.14405 unix 2 [ ACC ] STREAM LISTENING 1785049 21284/ssh-agent /tmp/ssh-W1Tl4i8HiftZ/agent.21283 

Of the two solutions, however, lsof clearly wins at the races:

$ time sudo netstat -ap | grep -E -- '(agent.21283|ssh-agent)' >/dev/null real 0m5.159s user 0m0.010s sys 0m0.019s $ time sudo lsof /tmp/ssh-W1Tl4i8HiftZ/agent.21283 >/dev/null real 0m0.120s user 0m0.038s sys 0m0.066s 

Yet another tool exists according to the netstat man page:

$ man netstat | grep -iC1 replace NOTES This program is mostly obsolete. Replacement for netstat is ss. Replacement for netstat -r is ip route. Replacement for netstat -i is ip -s link. Replacement for netstat -g is ip maddr. 

Sadly, ss also requires elevated permissions to identify the PID, but, it beats both netstat and lsof execution times:

$ time sudo ss -ap | grep -E "(agent.21283|ssh-agent)" u_str LISTEN 0 128 /tmp/ssh-w4fyViMab8wr/agent.10966 1765316 * 0 users:(("ssh-agent",pid=10967,fd=3)) u_str LISTEN 0 128 /tmp/ssh-0XemJ4YlRtVI/agent.14405 1777450 * 0 users:(("ssh-agent",pid=14406,fd=3)) u_str LISTEN 0 128 /tmp/ssh-W1Tl4i8HiftZ/agent.21283 1785049 * 0 users:(("ssh-agent",pid=21284,fd=3)) real 0m0.043s user 0m0.018s sys 0m0.021s 

In conclusion, it might seem that for some PID identification, it appears that elevated permissions are required.

Читайте также:  Года выпусков операционной системы linux

Note: Not all operating systems require elevated permissions. For example, SCO Openserver 5.0.7’s lsof seemed to work just fine without elevating permissions.

Caveat: This answer may fail with respect to the OP’s qualification for finding «the original creator» of the socket. In the example used, no doubt PID 21283 was the originator of the socket’s creation as this PID is identified in the socket name. Neither lsof nor netstat identified PID 21283 as the original creator, though clearly PID 21284 is the current maintainer.

Источник

Write inside a socket open by another process in Linux

Is it possible on Linux for a process to write inside a socket open by another one? Let’s say I open a connection to google.com using netcat:

myuser@linux:~$ nc google.com 80 
myuser@linux:~$ ls -la /proc/24105/fd totale 0 dr-x------ 2 myuser myuser 0 2012-03-10 19:01 . dr-xr-xr-x 7 myuser myuser 0 2012-03-10 19:01 .. lrwx------ 1 myuser myuser 64 2012-03-10 19:02 0 -> /dev/pts/12 lrwx------ 1 myuser myuser 64 2012-03-10 19:02 1 -> /dev/pts/12 lrwx------ 1 myuser myuser 64 2012-03-10 19:01 2 -> /dev/pts/12 lrwx------ 1 myuser myuser 64 2012-03-10 19:02 3 -> socket:[3947162] 
myuser@linux:~$ echo "GET / HTTP/1.1" >> /proc/24285/fd/3 bash: /proc/24285/fd/3: no such device or address 

Doing it as root doesn’t change the result. I can’t write inside the socket but I can write inside the stdin:

myuser@linux:~$ echo "GET / HTTP/1.1" >> /proc/24285/fd/0 myuser@linux:~$ 

But it’s not what I want to do. I was thinking: a Linux socket should be treated like a file, isn’t it? One or more processes can use the same socket, so why can’t I do this?

It doesnt look like it is possible. First this is a socket, not a fifo, so you cant just echo to it like a normal file. nc can do this, but trying to do so results in «Transport endpoint is not connected». Example command nc -v —send-only -U /proc/123/fd/3

Читайте также:  What is ssh daemon linux

what? Why should I use the -U (Unix socket) option? By the way I can’t understand how it can be useful

I found a bad workaround using gdb: gdb -p 24285 and then I can write inside the file descriptor using call write(3, «test»,4) . It works, but I would like to do the same thing from the procfile because the use of gdb requires to stop the process (so rises the risk of crashes or other bad things)

2 Answers 2

This isn’t possible because it would be difficult to implement and rarely useful. Sockets are a lot more complex than pipes:

  • Sockets are bidirectional.
  • There are different types of sockets. Some sockets aren’t streams of bytes (e.g. UDP sockets are datagram sockets, which send packets and not bytes).
  • Sockets perform multiplexing (and there’s some overloading between sockets used by servers waiting for connections and sockets used by actual opened connections).

Because sockets are bidirectional, they are often used to communicate under bidirectional protocols. If you inject data into the conversation, the other side might send a response to your data, and there is no way to dispatch the response to the right requester. This considerably reduces the usefulness of allowing data injection on sockets.

If you’re trying to contact the same server as an existing client and not tack onto an existing conversation, there is already a way to do that: contact the server in the same way (open a socket on the filesystem, or to a TCP or UDP port). If the socket is a nameless one between two processes, that’s a good hint that you aren’t supposed to join in, so the operating system doesn’t make it easy.

With a datagram socket (not the case here), you couldn’t directly inject data because the shell only understands streams of bytes, it doesn’t know to call send instead of write to send a packet.

If you have the cooperation of one endpoint, you can tell make use file descriptor passing 1 2 3.

Otherwise, you can make the process that has the socket open send the data itself, with ptrace (that’s what gdb uses under the hood). This suspends the process, very much by design, so that your dirty tricks don’t confuse the process too much. Even with the process suspended, you run a major risk of making the process’s data structures inconsistent with the reality of the data or environment modifications that you’ve injected. (Note that even if the system allowed injecting data over a socket, there would be a similar, if lesser, risk of confusing the process with these inconsistencies.)

Источник

Оцените статью
Adblock
detector