socat applies settings to wrong fd when accepting connection
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]
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:
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=
listen(3, 5) = 0
accept(3, {sa_family=AF_INET, sin_port=
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 @@
- 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 |