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>