Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 19 Aug 1996 05:05:12 +0200 (MET DST)
From:      Tor Egge <tegge@idt.ntnu.no>
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   kern/1512: Use of madvise may cause bad memory mappings
Message-ID:  <199608190305.FAA23808@ikke.idt.unit.no>
Resent-Message-ID: <199608190310.UAA09980@freefall.freebsd.org>

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

>Number:         1512
>Category:       kern
>Synopsis:       Use of madvise may may cause bad memory mappings
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Aug 18 20:10:03 PDT 1996
>Last-Modified:
>Originator:     Tor Egge
>Organization:
Norwegian University of Science and Technology, Trondheim, Norway
>Release:        FreeBSD 2.2-960801-SNAP i386
>Environment:

	FreeBSD ikke.idt.unit.no 2.2-960801-SNAP FreeBSD 2.2-960801-SNAP #0: Sat Aug 17 23:08:17 MET DST 1996     root@ikke.idt.unit.no:/usr/src/sys/compile/TEGGE  i386

>Description:

	Use of madvise to give hints about memory usage may cause 

	1. wrong data to be present in memory for the user process.
	   This may cause programs that relies on correct data to
	   fail. 

	2. Files not writeable and not owned by the user may get an 
           updated timestamp for last modified. 

        3. Files not writeable may get extended up to the nearest 
	   4K (pagesize) boundary, even though both the file 
	   had mode 444, open() used O_RDONLY and mmap used PROT_READ
	   and not PROT_WRITE.


>How-To-Repeat:

Problems 1 and 2:

Begin with a directory with 4400 files of different sizes, accumulated size
of all files should be around 1.6 GB. Count the number of zero-bytes
in all those files by selecting a random file and examine a random amount
of memory mapped from that file. Do this several times, and get different
number of zeros for some files.


Problems 3:

Debug the program, and print out some values of the memory locations where
the program has a bad memory mapping. The debugger disagrees with the
program about the contents of the memory, e.g. calling strcmp(a,b) may
give 65, printing a in gdb gives (0xef9d) "THAT" and printing b gives
(0x2034fffe) "THIS", e.g. the program thinks that b points to "TH", while
the debugger things that b points to "THIS".

Appended here is a short cut from a diff between two results piped through
 "sort +1n +2". The number of zero-bytes in some of the files vary :-(

Appended is also a program to count zero-bytes in a set of files (almost
all files in current directory if no argument is given) using a pseudo-random
access pattern.

-----
***************
*** 2842,2848 ****
       10149      61428 ftp.westfield.com
       10152      61442 ftp.itis.com
       10176      61589 ftp.wednet.edu
!      11600      61671 ftp.tno.nl
       10751      61749 ftp.pure.com
       10610      62035 ftp.icsi.berkeley.edu
       12911      62171 ftp.intac.com
--- 2842,2848 ----
       10149      61428 ftp.westfield.com
       10152      61442 ftp.itis.com
       10176      61589 ftp.wednet.edu
!      10894      61671 ftp.tno.nl
       10751      61749 ftp.pure.com
       10610      62035 ftp.icsi.berkeley.edu
       12911      62171 ftp.intac.com
***************
*** 3693,3699 ****
       48696     408848 ftp.idg.nl
       75423     409817 ftp.wyoming.com
       63850     413662 ftp.crl.research.digital.com
!      52633     413944 ftp.uam.es
       61658     414617 ftp.forest.dnj.ynu.ac.jp
       48689     415714 ftp.cli.unipi.it
       62770     415728 ftp.hitachi-sk.co.jp
--- 3693,3699 ----
       48696     408848 ftp.idg.nl
       75423     409817 ftp.wyoming.com
       63850     413662 ftp.crl.research.digital.com
!      52620     413944 ftp.uam.es
       61658     414617 ftp.forest.dnj.ynu.ac.jp
       48689     415714 ftp.cli.unipi.it
       62770     415728 ftp.hitachi-sk.co.jp
------
#include <sys/types.h>
#include <sys/param.h>
#include <sys/mman.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/errno.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <dirent.h>
#include <string.h>
#include <assert.h>


#define MAXFILES 6000
char *names[MAXFILES];
char *bases[MAXFILES];
char *ends[MAXFILES];
int fds[MAXFILES];
int sizes[MAXFILES];
int zeros[MAXFILES];
char *poss[MAXFILES];
unsigned int lastframe[MAXFILES];

unsigned int pagesize;

int main(int argc,char **argv)
{
  struct stat stbuf;
  unsigned int i;
  DIR *dirp;
  struct dirent *direntp;
  unsigned int ninf=0;
  char *pos;
  unsigned int frame;
  unsigned int outerlen;
  unsigned int innerlen;

  srandom(time(NULL));
  if (argc>1) {
    for (i=1;i<argc;i++) {
      if (!strncmp(argv[i],".",1) ||
	  !strcmp(argv[i],"tracebacksyms") ||
	  !strcmp(argv[i],"mergesites.core") ||
	  !strcmp(argv[i],"core.mergesites") ||
	  !strcmp(argv[i],"core"))
	continue;
      if (ninf>=MAXFILES) 
	{
	  fprintf(stderr,"Too many input files\n");
	  exit(1);
	}
      names[ninf++]=strdup(argv[i]);
    }
  } else {
    dirp=opendir(".");
    assert(dirp);
    while ((direntp=readdir(dirp))) {
      if (!strncmp(direntp->d_name,".",1) ||
	  !strcmp(direntp->d_name,"tracebacksyms") ||
	  !strcmp(direntp->d_name,"mergesites.core") ||
	  !strcmp(direntp->d_name,"core.mergesites") ||
	  !strcmp(direntp->d_name,"core"))
	continue;
      if (ninf>=MAXFILES) 
	{
	  fprintf(stderr,"Too many input files\n");
	  exit(1);
	}
      names[ninf++]=strdup(direntp->d_name);
    }
    closedir(dirp);
  }

  for (i=0;i<ninf;i++) {
    fds[i] = open(names[i],O_RDONLY,0);
    if (fds[i]<0) {
      printf("Could not open %s: %s\n",names[i],strerror(errno));
      exit(1);
    }
    
    if (fstat(fds[i],&stbuf)) {
      printf("fstat failed for %s: %s\n",names[i],strerror(errno));
      exit(1);
    }
  
    bases[i] = 
      mmap(0,(size_t) stbuf.st_size,PROT_READ,MAP_SHARED,fds[i],(off_t) 0);
    if (((int) bases[i]) == -1) {
      printf("Failed mmap for %s: %s\n",names[i],strerror(errno));
      exit(1);
    }

    zeros[i]=0;
    lastframe[i]=((unsigned int) bases[i]) & ((unsigned int) (-pagesize));
    poss[i]=bases[i];
    ends[i]=bases[i] + stbuf.st_size;
    sizes[i] = stbuf.st_size;

    close(fds[i]);
    fds[i] = -1;
  }

  printf("Mapped %d files\n",ninf);
  fflush(stdout);

  pagesize =getpagesize();

  while (ninf) {
    i = ((unsigned int) random()) % ninf;
    outerlen = ((unsigned int) random()) % 32768;
    if ((unsigned int) poss[i]+outerlen>(unsigned int) ends[i])
      outerlen=ends[i] - poss[i];
    
    while (outerlen) {
      innerlen = ((unsigned int) random()) % 512;
      if (innerlen>outerlen)
	innerlen = outerlen;

      outerlen -= innerlen;
      pos = poss[i];
      while (innerlen) {
	if (!*pos) zeros[i]++;
	innerlen--;
	pos++;
      }
      poss[i] = pos;

      frame = (((unsigned int) pos) & (unsigned int) (-pagesize));
      if (frame != lastframe[i]) {
	madvise((caddr_t) bases[i] + lastframe[i],frame-lastframe[i],MADV_DONTNEED);
	madvise((caddr_t) (frame+pagesize),2*pagesize,MADV_WILLNEED);
	lastframe[i]=frame;
      }
    }
    if ((unsigned int) poss[i]>=(unsigned int) ends[i]) {
      assert(poss[i]==ends[i]);
      printf("%10d %10d %s\n",zeros[i],sizes[i],names[i]);
      fflush(stdout);
      zeros[i] = zeros[ninf-1];
      sizes[i] = sizes[ninf-1];
      bases[i] = bases[ninf-1];
      fds[i] = fds[ninf-1];
      names[i] = names[ninf-1];
      lastframe[i]=lastframe[ninf-1];
      poss[i]=poss[ninf-1];
      ends[i]=ends[ninf-1];
      ninf--;
    }
  }
}
-----
>Fix:
None.
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199608190305.FAA23808>