Subject: lib/9349: mmap() requires PROT_READ even if only writing
To: None <gnats-bugs@gnats.netbsd.org>
From: Mike <mac@NetBSD.Advantrix.Com>
List: netbsd-bugs
Date: 02/04/2000 08:36:56
>Number:         9349
>Category:       lib
>Synopsis:       mmap() requires PROT_READ even if only writing
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    lib-bug-people (Library Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Feb  4 08:36:00 2000
>Last-Modified:
>Originator:     Mike Cheponis
>Organization:
	
>Release:        1.4P
>Environment:
	K6-2/400 128M 18G ATAPI, -current 1.4P
System: NetBSD NetBSD 1.4P NetBSD 1.4P (USB) #8: Sat Jan 22 12:43:33 PST 2000 mac@NetBSD:/usr/src/sys/arch/i386/compile/USB i386


>Description:
	mmap requires PROT_READ even if only writing
>How-To-Repeat:

/*
 * copyfile.c
 * Compile this program and run it like this: copyfile copyfile.c foo.c
 * gdb says: Program received signal SIGSEGV, Segmentation fault.
 * 0x480cba66 in memcpy ()
 */

#include <stdio.h>
#include <sys/mman.h>
#include <fcntl.h>

main(int argc, char **argv){
  int input, output;
  size_t filesize;
  void *source, *target;
  char endchar = '\0';

  /* Check that the correct # of parameters have been passed */
  if(argc != 3){
    fprintf(stderr,"usage: copyfile source target\n");
    exit (1);
  }

  /* Open both files */
  if( (input = open(argv[1], O_RDONLY)) == -1){
    fprintf(stderr, "Error opening input file %s\n", argv[1]);
    exit(1);
  }

  if( (output = open(argv[2], O_RDWR | O_CREAT | O_TRUNC, 0666)) == -1){
    fprintf(stderr, "Error opening output file %s\n", argv[2]);
    exit(2);
  }/* Note that the input file is automatically closed when exiting */

  /*Create 2nd file as same size as first file */
  filesize = lseek(input, 0, SEEK_END);
  lseek(output, filesize-1, SEEK_SET);
  write(output, &endchar, 1);

  /* memory map both input and output files */
  if( (source = mmap(0, filesize, PROT_READ, MAP_SHARED, input, 0)) ==
                                                              (void *)-1){
    fprintf(stderr,"Error mapping input file %s\n", argv[1]);
    exit(1);
  }

  if( (target = mmap(0, filesize, PROT_WRITE, MAP_SHARED, output, 0)) ==
                                                              (void *)-1){
    fprintf(stderr,"Error mapping output file %s\n", argv[2]);
    exit(2);
  }

  printf("in=%x out=%x, filesize= %d\n",source,target,filesize);

  /* copy */
  memcpy(target, source, filesize);

  /* Unmap files */

  munmap(source, filesize);
  munmap(target, filesize);

  exit(0);/* both files will be closed upon exit automatically by OS */
}


>Fix:
	The temporary fix is to "or" PROT_READ into the target, like this:

     target = mmap(0, filesize, PROT_READ | PROT_WRITE, MAP_SHARED, output, 0)

	But this obviously doesn't fix the improper behavior of mmap().

	Thanks to Lennart Augustsson <lennart@augustsson.net> for telling me
	how to work around the problem.



>Audit-Trail:
>Unformatted: