socat applies settings to wrong fd when accepting connection

Bug #1204795 reported by Roman Fiedler
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
socat (Ubuntu)
New
Low
Unassigned

Bug Description

After accept socket options are applied to the listening socket again, but not to the accepted connection's socket. This can be seen when e.g. requesting TCP-keepalives to be sent:

When connecting with socat to a non-keepalive listener everything works as expected:

socat TCP4:[IP]:1234,keepalive=1,keepidle=1,keepintvl=1,keepcnt=3 -

setsockopt(3, SOL_TCP, TCP_KEEPIDLE, [1], 4) = 0
setsockopt(3, SOL_TCP, TCP_KEEPINTVL, [1], 4) = 0
setsockopt(3, SOL_TCP, TCP_KEEPCNT, [3], 4) = 0
setsockopt(3, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0

and keepalives are sent each second.

When using a keepalive-listener and non-keepalive sender, no keepalives are sent. With

socat TCP4-LISTEN:1234,reuseaddr=1,keepalive=1,keepidle=1,keepintvl=1,keepcnt=3 -

following trace can be captured:

setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 <<<< sets keep alive on listening socket
setsockopt(3, SOL_TCP, TCP_KEEPIDLE, [1], 4) = 0
setsockopt(3, SOL_TCP, TCP_KEEPINTVL, [1], 4) = 0
setsockopt(3, SOL_TCP, TCP_KEEPCNT, [3], 4) = 0
fcntl64(3, F_SETFD, FD_CLOEXEC) = 0
bind(3, {sa_family=AF_INET, sin_port=htons(1234), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
listen(3, 5) = 0
accept(3, {sa_family=AF_INET, sin_port=htons(57251), sin_addr=inet_addr("[IP]")}, [16]) = 5
setsockopt(3, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0

so the keep-alive is set again on the server socket before bind and after accept, but not on the accepted socket (5). I haven't checked the kernel specs if keepalive should be inherited with accept, but at least it seems, that this is not the case.

The bug has little to no security implications unless security-relevant options in socat are applied that way to new sockets. On our systems, that bug lead only to a memory starvation DOS on two small virtual machines that could not cope with the high number of socat processes due to abandoned TCP-connections when statefull firewalls in between were frequently restarted.

The following !UNTESTED! patch to the socat trunk should fix it.

--- xio-listen.c 2013-03-22 06:43:41.000000000 +0000
+++ xio-listen.c 2013-07-19 08:34:09.644931068 +0000
@@ -277,8 +277,8 @@
               sockaddr_info((struct sockaddr *)pa, pas,
                             infobuff, sizeof(infobuff)));

- applyopts(xfd->fd, opts, PH_FD);
- applyopts(xfd->fd, opts, PH_CONNECTED);
+ applyopts(ps, opts, PH_FD);
+ applyopts(ps, opts, PH_CONNECTED);

       if (dofork) {
         pid_t pid; /* mostly int; only used with fork */

Maintainer has confirmed the bug in trunk and plans to release a patch also.

Affected version:
 1.7.1.3-1.2 multipurpose relay for bidirectional data transfer

Changed in socat (Ubuntu):
importance: Undecided → Low
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.