SOCK_STREAM socket + bind without calling listen makes address hidden

From: Manvendra Bhangui
Date: Thu Aug 13 2015 - 02:05:46 EST


Stumbled on an issue of imap server refusing to start on TCP port
993 with error EADDRINUSE inspite of netstat, lsof, ss programs
indicating no process has bound on tcp port 993

On debugging found the issue to be with portreserve program.
http://linux.die.net/man/1/portreserve

But portreserve is not the issue. It is doing what it is expected to
do - grab and reserve a port

None of the programs - netstat, lsof, ss could show that the
portreserve port has bound on the socket 993. Killing the portreserve
program or calling portrelease program resolves the issue.

I can simulate the same issue by writing a code which just calls
socket() and bind() and nothing that I know of can find out which
program has bound on an address

Shouldn't there be a socket state which netstat / lsof / ss can reveal
which process has bound on an address without calling listen()? I
could think of rogue programs which calls socket() + bind(), without
calling listen(), to prevent programs from starting up and left with a
clueless admin trying to figure out which process has bound an address

start portreserve service to reserve imaps port

# systemctl enable portreserve

## get the pid of portreserve
# ps -ef|grep portreserve
root 29771 1 0 11:14 ? 00:00:00 /sbin/portreserve
root 29773 28654 0 11:14 pts/1 00:00:00 grep --color=auto portreserve

run lsof to find all open ports. You can see that for TCP socket, the
address is not shown.
it just shows "protocol: TCP"
For UDP it shows the address

# lsof -p 29771
lsof: WARNING: can't stat() fuse.gvfsd-fuse file system /run/user/1000/gvfs
Output information may be incomplete.
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
portreser 29771 root cwd DIR 253,0 4096 2 /
portreser 29771 root rtd DIR 253,0 4096 2 /
portreser 29771 root txt REG 253,0 15792 2112388
/usr/sbin/portreserve
portreser 29771 root mem REG 253,0 62072 2109005
/usr/lib64/libnss_files-2.20.so
portreser 29771 root mem REG 253,0 2082456 2101348
/usr/lib64/libc-2.20.so
portreser 29771 root mem REG 253,0 163176 2098678
/usr/lib64/ld-2.20.so
portreser 29771 root 0uW REG 0,19 6 175038
/run/portreserve.pid
portreser 29771 root 1u unix 0xffff8801fd24c600 0t0 175039
/var/run/portreserve/socket
portreser 29771 root 4u sock 0,8 0t0 175043
protocol: TCP
portreser 29771 root 5u IPv4 175044 0t0 UDP *:imaps

same with the netstat program which shows only the udp port

# netstat -anp |grep 993
udp 0 0 0.0.0.0:993 0.0.0.0:*
29771/portreserve

same with the ss program which also shows only the udp port
# ss -a| egrep "993|imaps"
udp UNCONN 0 0 *:ipproto-993 *:*


try is a simple program which binds on both tcp port 993 (ipv4 as well as ipv6)

# ./try
bind: Address already in use
#

socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 3
setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
setsockopt(3, SOL_SOCKET, SO_LINGER, {onoff=1, linger=60}, 8) = 0
bind(3, {sa_family=AF_INET, sin_port=htons(993),
sin_addr=inet_addr("0.0.0.0")}, 16) = -1 EADDRINUSE (Address already
in use)
close(3) = 0
socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP) = 3
setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
setsockopt(3, SOL_SOCKET, SO_LINGER, {onoff=1, linger=60}, 8) = 0
bind(3, {sa_family=AF_INET6, sin6_port=htons(993), inet_pton(AF_INET6,
"::", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = -1
EADDRINUSE (Address already in use)

--
Regards Manvendra - http://www.indimail.org
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/