Public bug reported:

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

** Affects: socat (Ubuntu)
     Importance: Undecided
         Status: New

-- 
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/1204795

Title:
  socat applies settings to wrong fd when accepting connection

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/socat/+bug/1204795/+subscriptions

-- 
ubuntu-bugs mailing list
ubuntu-bugs@lists.ubuntu.com
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs

Reply via email to