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: