5

I need to identify the cgroup of a process given the socket. Specifically, I have a process on the same machine that is calling my process using tcp, and I need to identify the process or its cgroup. The tcp requirement is because I'm simulating a third party API. I need to return different data depending on which process is calling me. One solution is to determine the socket using /proc/net/tcp, from which I can get the inode for the socket, and then to iterate over /proc/*/fd to find that inode listed. Is there a direct way to map from a (I assume a sockfs) inode to its PID without this iteration?

3

In general, to find what's at the other end of a socket, you need to iterate through /proc. This can of course mean letting an existing tool such as netstat, lsof or ss do it for you.

The reason for this is that a socket can be opened by different processes. Once a process has opened a socket, it can fork, and the children can change their privileges and switch to different namespaces. It's also possible to pass file descriptors from a process to an unrelated process, using anciliary data on a unix socket. So arbitrary processes can have the same socket open. There is no such thing as “the PID of a socket”, only “the PIDs of a socket”.

While this doesn't prove that there's no way to enumerate the PIDs given the socket, it would be very difficult to design such an interface, especially when you consider that non-root users don't get to know when files are opened by processes running as a different user. Access through /proc enforces security via permissions, and I'm not aware of any other interface to get the same data. Also, fuser, lsof, netstat and ss all enumerate /proc; if there was another interface, I'd expect someone to use it. So I'm pretty sure that there's no other way.

  • 1
    You may also be able to use the NETLINK layer to find the information but, as you correctly point out, there's the possibility for more than one process to have the same socket open. NETLINK can give you the inode and uid of the process (see oidentd sources for an example) but not the process ID. – Stephen Harris Aug 9 '16 at 0:22
  • @StephenHarris When I wrote this answer I wondered how identd gets the user information. I think you're saying that it's recorded as the user owning the socket file? Which indeed would give a UID but no PID (after all, it still works if the process that originally created the socket is dead). – Gilles Aug 9 '16 at 0:51
  • Right. struct tcpdiagmsg has various fields (family, rqueue, wqueue, uid, inode and others) but no process ID field. Since RFC1413 (IDENT) only really cares about username it's good enough for oidentd :-) – Stephen Harris Aug 9 '16 at 0:56
  • Is there a C interface to ask the kernel for this information, or does one have to go through the '/proc' file system? – jamie Aug 22 '16 at 22:29
  • @jamie As I explain in my last paragraph, while I haven't made an exhaustive review of the system calls to make sure there's no other way besides /proc, I don't think there is, because all of the common programs to access this information use /proc. – Gilles Aug 22 '16 at 22:31
0

if you know the tcp port number then you can use this command in your terminal:

$ lsof | grep TCP | grep your_port_number

Eg: lsof | grep TCP | grep 1234

0

To determine the cgroup, you can refer to sk_cgrp_data field in struct sock. This is an example from __cgroup_bpf_run_filter_sock_ops() in kernel/bpf/cgroup.c:

struct cgroup *cgrp = sock_cgroup_ptr(&sk->sk_cgrp_data)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.