Re: [patch] af_unix fix for a panic a DoS and a memory leak [Re:

Andrea Arcangeli (andrea@e-mind.com)
Tue, 2 Mar 1999 18:39:33 +0100 (CET)


On Tue, 2 Mar 1999 kuznet@ms2.inr.ac.ru wrote:

>I see... but what to do then? We did not remove syn skb and not yet

What do you mean with "what to do then"?

Excuse but my bad English is hurting my understanding again.

Yesterday night I tried heavily unix-domain-sockets with a threded proggy
written exactly for this purpose by me. There's been no problem so far and
I think there are no SMP races in the af_unix code.

Here my proggy. The implementation could be a bit bad (btw is there a
smarter way to kill all pending zombie tasks without having to recall
waitonpid(WNOHANG) for every last child previously launched?) but it
should stress the basic functionality of unix-sockets quite well.

There's to say that it only test stream sockets.

/*
* Test-suite for unix-sockets in Linux-2.2.2.
*
* Copyright (C) 1999 Andrea Arcangeli
*/

#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/un.h>

#define SIZE (1024*1024)
#define NR 20
#define THREAD 100000

static int pids[THREAD][2];

static int do_accept(int sock)
{
int addr, len, sk, pid;
char buf[SIZE];

sk = accept(sock, NULL, 0);

if (sk <= 0)
perror("accept"), exit(1);

switch ((pid = fork()))
{
int i;
default:
close(sk);
return pid;
case -1:
perror("fork");
exit(1);
case 0:
for (i = 0; i < NR; i++)
if (read(sk, buf, SIZE) <= 0)
perror("client read"), exit(1);
_exit(0);
}
return 0;
}

static void server(void)
{
struct sockaddr_un saddr;

int sock, i;

sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0)
perror("socket"), exit(1);

bzero((char *)&saddr, sizeof(saddr));
saddr.sun_family = AF_UNIX;
sprintf(saddr.sun_path, "/tmp/try");

if (bind(sock, (struct sockaddr_un *)&saddr, sizeof(saddr)) == -1)
perror("bind"), exit(1);

listen(sock, THREAD);

for (i = 0; i < THREAD; i++)
{
int j;

pids[i][0] = do_accept(sock);

for (j = 0; j <= i; j++)
waitpid(pids[j][0], NULL, WNOHANG);
}

close(sock);

unlink("/tmp/try");
}

static int do_connect(void)
{
struct sockaddr_un saddr;
char buf[SIZE];
int i, sock, pid;

switch ((pid = fork()))
{
default:
return pid;
case -1:
perror("fork");
exit(1);
case 0:
}

bzero(buf, SIZE);
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0)
perror("socket"), exit(1);

bzero((char *)&saddr, sizeof(saddr));
saddr.sun_family = AF_UNIX;
sprintf(saddr.sun_path, "/tmp/try");

if (connect(sock, (struct sockaddr_un *)&saddr,
sizeof(saddr)) == -1)
perror("connect"), exit(1);

for (i = 0; i < NR; i++)
if (write(sock, buf, SIZE) < 0)
perror("server write"), exit(1);
close(sock);
_exit(0);
return 0;
}

static void client(void)
{
int i;

for (i = 0; i < THREAD; i++)
{
int j;

pids[i][1] = do_connect();

for (j = 0; j <= i; j++)
waitpid(pids[j][1], NULL, WNOHANG);
}
}

main()
{
switch (fork())
{
default:
server();
break;
case 0:
client();
break;
case -1:
perror("fork");
exit(1);
}
}

Andrea Arcangeli

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/