Linux 2.0.x networking bug related to SYN cookies

Chris Evans (chris@ferret.lmh.ox.ac.uk)
Sun, 29 Mar 1998 03:25:04 +0100 (BST)


OK,

This bug's annoyed me for long enough now. It is pretty reproducable and
should be easy for someone to track down and squash if they know the
networking code.

Essentially there seems a high correlation between the "possible SYN
flooding, sending cookies" message and sockets being left stuck in the
CLOSE stack. The sockets stuck are indeed the same ones upon which the
alleged SYN flooing occured.

In my case, I'm pretty sure it's not an attack.

Probably caused by some race/missing kfree_skb in the kernel, who knows.

Anyway, some data. First what a stuck socket looks like:

tcp 0 0 163.1.138.204:14090 0.0.0.0:* CLOSE
on (1.83/0)
tcp 0 0 163.1.138.204:26702 0.0.0.0:* CLOSE
on (6.44/0)
tcp 0 0 163.1.138.204:27274 0.0.0.0:* CLOSE
on (3.58/0)
tcp 0 0 163.1.138.204:27857 0.0.0.0:* CLOSE
on (2.82/0)
tcp 0 0 163.1.138.204:29004 0.0.0.0:* CLOSE
on (6.54/0)

And the messages from the kernel:

Warning: possible SYN flood from 195.96.18.181 on 163.1.138.204:14090.
Sending cookies.
Warning: possible SYN flood from 195.96.18.181 on 163.1.138.204:26616.
Sending cookies.
Warning: possible SYN flood from 195.96.18.181 on 163.1.138.204:26937.
Sending cookies.

[etc.]

I was actually able to reproduce this pretty reliably by writing this
little program, just run it (with SYN_COOKIES enable. RST cookies are
off).

eg ./a.out 15000 <--- watch a stuck 15000 appear!

#include <netinet/in.h>

#include <sys/types.h>
#include <sys/socket.h>

int
main(int argc, char** argv)
{
struct sockaddr_in addr;
int at_sock;
int bombard;
int kill_sock = atoi(argv[1]);

int sockfd = socket(AF_INET, SOCK_STREAM, 6);

addr.sin_family = AF_INET;
addr.sin_port = htons(kill_sock);
addr.sin_addr.s_addr = htonl(INADDR_ANY);

if (bind(sockfd, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)) < 0) {
perror("bind");
exit(1);
}

if (listen(sockfd, 4) < 0) {
perror("listen");
exit(1);
}

/* Now bombard the connections... */
bombard = 20;
while (bombard--) {
int newfd = socket(AF_INET, SOCK_STREAM, 6);
addr.sin_family = AF_INET;
addr.sin_port = htons(kill_sock);
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);

if (connect(newfd, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)) < 0) {
perror("connect");
}
close(newfd);
}
}

For some reason stuck sockets _really_ wind me up. Irrational I know :) As
far as I can see this is the only regular socket "stuck" bug left, the
TIME_WAIT/CLOSE_WAIT stuck one present in 2.0.27 was fixed in ~2.0.30.
Would be nice to get this one cleaned up.

Oh, I suppose a small amount of kernel memory is consumed by 1) the socket
struct, 2) the timer, 3) possibly a cookie SKB, if it hasn't been freed.
So there's very minor DoS implications I suppose....

Happy to test any patchs :)

Cheers
Chris

P.S. oops, kernel 2.0.32 did I say, after 2.0.33 liked corrupting run
queues/wait queues for me

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu