<p>Sorry about the long question post, but I think it can be useful to others to learn how this works.</p>
<h1>What I know:</h1>
<p>On any linux <em><strong>host</strong></em> (<em>not using docker container</em>), I can look at <code>/proc/net/tcp</code> to extract information tcp socket related.</p>
<p>So, I can detect the ports in <code>LISTEN</code> state with:</p>
<pre class="lang-sh prettyprint-override"><code>cat /proc/net/tcp | 
 grep &quot; 0A &quot; | 
  sed 's/^[^:]*: \(..\)\(..\)\(..\)\(..\):\(....\).*/echo $((0x\4)).$((0x\3)).$((0x\2)).$((0x\1)):$((0x\5))/g' | 
   bash
</code></pre>
<p>Results:</p>
<pre><code>0.0.0.0:111
10.174.109.1:53
127.0.0.53:53
0.0.0.0:22
127.0.0.1:631
0.0.0.0:8000
</code></pre>
<p><code>/proc/net/tcp</code> gives <code>UID</code>, <code>GID</code>, unfortunately does not provides the <code>PID</code>. But returns the <code>inode</code>. That I can use to discover the <code>PID</code> using it as file descriptor.</p>
<p>So one way is to search <code>/proc</code> looking for the <code>inode</code> socket. It's slow, but works on host:</p>
<pre class="lang-sh prettyprint-override"><code>cat /proc/net/tcp |
 grep &quot; 0A &quot; |
  sed 's/^[^:]*: \(..\)\(..\)\(..\)\(..\):\(....\).\{72\}\([^ ]*\).*/echo $((0x\4)).$((0x\3)).$((0x\2)).$((0x\1)):$((0x\5))\\\t$(find \/proc\/ -type d -name fd 2&gt;\/dev\/null \| while read f\; do ls -l $f 2&gt;\/dev\/null \| grep -q \6 \&amp;\&amp; echo $f; done)/g' |
   bash
</code></pre>
<p>output:</p>
<pre><code>0.0.0.0:111     /proc/1/task/1/fd /proc/1/fd /proc/924/task/924/fd /proc/924/fd
10.174.109.1:53 /proc/23189/task/23189/fd /proc/23189/fd
127.0.0.53:53   /proc/923/task/923/fd /proc/923/fd
0.0.0.0:22      /proc/1194/task/1194/fd /proc/1194/fd
127.0.0.1:631   /proc/13921/task/13921/fd /proc/13921/fd
0.0.0.0:8000    /proc/23122/task/23122/fd /proc/23122/fd
</code></pre>
<h2>Permission tip 1: You will only see what you have permission to look at.</h2>
<h2>Permission tip 2: fake <strong><code>root</code></strong> used in containers does not have access to all file descriptors in <code>/proc/*/fd</code>. You need to query it for each user.</h2>
<p>If you run as normal user the results are:</p>
<pre><code>0.0.0.0:111
10.174.109.1:53
127.0.0.53:53
0.0.0.0:22
127.0.0.1:631
0.0.0.0:8000    /proc/23122/task/23122/fd /proc/23122/fd
</code></pre>
<p>Using <code>unshare</code> to isolate environment it works as expected:</p>
<pre class="lang-sh prettyprint-override"><code>$ unshare -r --fork --pid unshare -r --fork --pid --mount-proc -n bash
# ps -fe
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  2 07:19 pts/6    00:00:00 bash
root       100     1  0 07:19 pts/6    00:00:00 ps -fe
# netstat -ntpl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
# python -m SimpleHTTPServer &amp;
[1] 152
# Serving HTTP on 0.0.0.0 port 8000 ...
netstat -ntpl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:8000            0.0.0.0:*               LISTEN      152/python          
# cat /proc/net/tcp |
&gt;  grep &quot; 0A &quot; |
&gt;   sed 's/^[^:]*: \(..\)\(..\)\(..\)\(..\):\(....\).\{72\}\([^ ]*\).*/echo $((0x\4)).$((0x\3)).$((0x\2)).$((0x\1)):$((0x\5))\\\t$(find \/proc\/ -type d -name fd 2&gt;\/dev\/null \| while read f\; do ls -l $f 2&gt;\/dev\/null \| grep -q \6 \&amp;\&amp; echo $f; done)/g' |
&gt;    bash
0.0.0.0:8000    /proc/152/task/152/fd /proc/152/fd
# ls -l /proc/152/fd
total 0
lrwx------ 1 root root 64 mai 25 07:20 0 -&gt; /dev/pts/6
lrwx------ 1 root root 64 mai 25 07:20 1 -&gt; /dev/pts/6
lrwx------ 1 root root 64 mai 25 07:20 2 -&gt; /dev/pts/6
lrwx------ 1 root root 64 mai 25 07:20 3 -&gt; 'socket:[52409024]'
lr-x------ 1 root root 64 mai 25 07:20 7 -&gt; /dev/urandom
# cat /proc/net/tcp
  sl  local_address rem_address   st tx_queue rx_queue tr tm-&gt;when retrnsmt   uid  timeout inode                                                     
   0: 00000000:1F40 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 52409024 1 0000000000000000 100 0 0 10 0 
</code></pre>
<p>Inside a docker container in my host, it seems to work in same way.</p>
<h1>The problem:</h1>
<p>I have a container inside a kubernetes pod running jitsi. Inside this container, I am unable to get the PID of the service listening the ports.</p>
<p>Nor after installing netstat:</p>
<pre class="lang-sh prettyprint-override"><code>root@jitsi-586cb55594-kfz6m:/# netstat -ntpl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:5222            0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:5269            0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:8888            0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:5280            0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:5347            0.0.0.0:*               LISTEN      -                   
tcp6       0      0 :::5222                 :::*                    LISTEN      -                   
tcp6       0      0 :::5269                 :::*                    LISTEN      -                   
tcp6       0      0 :::5280                 :::*                    LISTEN      -                   
</code></pre>
<pre class="lang-sh prettyprint-override"><code># ps -fe
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 May22 ?        00:00:00 s6-svscan -t0 /var/run/s6/services
root        32     1  0 May22 ?        00:00:00 s6-supervise s6-fdholderd
root       199     1  0 May22 ?        00:00:00 s6-supervise jicofo
jicofo     203   199  0 May22 ?        00:04:17 java -Xmx3072m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp -Dnet.java.sip.communicator.SC_HOME_DIR_LOCATION=/ -Dnet.java.sip.communicator.SC_HOME_DIR_NAME=config -Djava
root      5990     0  0 09:48 pts/2    00:00:00 bash
root     10926  5990  0 09:57 pts/2    00:00:00 ps -fe
</code></pre>
<h1>Finally the Questions:</h1>
<h2>a) Why can't I read the file descriptors of the proccess listening port 5222 ?</h2>
<pre><code>root@jitsi-586cb55594-kfz6m:/# cat /proc/net/tcp | grep &quot; 0A &quot;
    0: 00000000:1466 00000000:0000 0A 00000000:00000000 00:00000000 00000000   101        0 244887827 1 ffff9bd749145800 100 0 0 10 0                 
...
root@jitsi-586cb55594-kfz6m:/# echo $(( 0x1466 ))
5222
root@jitsi-586cb55594-kfz6m:/# ls -l  /proc/*/fd/* 2&gt;/dev/null | grep 244887827                                                     
root@jitsi-586cb55594-kfz6m:/# echo $?
1
root@jitsi-586cb55594-kfz6m:/# su - svc
svc@jitsi-586cb55594-kfz6m:~$ id -u
101
svc@jitsi-586cb55594-kfz6m:~$ ls -l /proc/*/fd/* 2&gt;/dev/null | grep 244887827
svc@jitsi-586cb55594-kfz6m:~$ echo $?
1
</code></pre>
<h2>b) There is another way to list <code>inode</code> and link it to a <code>pid</code> without searching <code>/proc/*/fd</code> ?</h2>
<h2>Update 1:</h2>
<p>Based on <a href="https://stackoverflow.com/users/5937420/anton-kostenko">Anton Kostenko</a> tip, I looked to AppArmor. It's not the case because the server don't use AppArmor, but searching, took me to SELinux.</p>
<p>In a ubuntu machine where AppArmor is running, I got:</p>
<pre class="lang-sh prettyprint-override"><code>$ sudo apparmor_status  | grep dock                                                                              
   docker-default
</code></pre>
<p>In the OKE(Oracle Kubernetes Engine, my case) node there is no AppArmor. I got SELinux instead:</p>
<pre class="lang-sh prettyprint-override"><code>$ man selinuxenabled | grep EXIT -A1
EXIT STATUS
       It exits with status 0 if SELinux is enabled and 1 if it is not enabled.
$ selinuxenabled &amp;&amp; echo $?
0
</code></pre>
<p>Now, I do believe that <code>SELinux</code> is blocking the <code>/proc/*/fd</code> listing from root inside the container. But I don't know yet how to unlock it.</p>
<h1>References:</h1>
<p><a href="https://jvns.ca/blog/2016/10/10/what-even-is-a-container/" rel="nofollow noreferrer">https://jvns.ca/blog/2016/10/10/what-even-is-a-container/</a></p>

<p>The issue is solved by adding the POSIX capability: <code>CAP_SYS_PTRACE</code></p>
<p>I'm my case the container are under kubernetes orchestration.</p>
<p><a href="https://kubernetes.io/docs/tasks/configure-pod-container/security-context/" rel="nofollow noreferrer">this reference</a> explains about <code>kubectl</code> and <code>POSIX Capabilities</code></p>
<p>So I have</p>
<pre><code>root@jitsi-55584f98bf-6cwpn:/# cat /proc/1/status | grep Cap
CapInh: 00000000a80425fb
CapPrm: 00000000a80425fb
CapEff: 00000000a80425fb
CapBnd: 00000000a80425fb
CapAmb: 0000000000000000
</code></pre>
<p>So I careful read the <a href="https://man7.org/linux/man-pages/man7/capabilities.7.html" rel="nofollow noreferrer">POSIX Capabilities Manual</a>. But even adding <code>CAP_SYS_ADMIN</code>, the <code>PID</code> does not appear on <code>netstat</code>. So I tested all capabilities. <code>CAP_SYS_PTRACE</code> is <em><strong>The Chosen One</strong></em></p>
<pre><code>root@jitsi-65c6b5d4f7-r546h:/# cat /proc/1/status | grep Cap
CapInh: 00000000a80c25fb
CapPrm: 00000000a80c25fb
CapEff: 00000000a80c25fb
CapBnd: 00000000a80c25fb
CapAmb: 0000000000000000
</code></pre>
<p>So here my deployment spec change:</p>
<pre><code>...
spec:
  ...
  template:
    ...
    spec:
      ...
      containers:
        ...
        securityContext:
          capabilities:
            add:
            - SYS_PTRACE
...
</code></pre>
<p>Yet I don't know what security reasons <code>selinux</code> use to do it. But for now it's good enough for me.</p>
<p>References:</p>
<ul>
<li><a href="https://man7.org/linux/man-pages/man7/capabilities.7.html" rel="nofollow noreferrer">https://man7.org/linux/man-pages/man7/capabilities.7.html</a></li>
<li><a href="https://kubernetes.io/docs/tasks/configure-pod-container/security-context/" rel="nofollow noreferrer">https://kubernetes.io/docs/tasks/configure-pod-container/security-context/</a></li>
</ul>
