Hi,
I have a problem with mprotect and mmap under Solaris 2.5.1. Briefly,
when using mprotect to make one page of a mmaped file readable,
subsequent pages are also readable as far as the application is
concerned. pmap gives correct permissions, but there is no page
fault. Strangely enough, if the mmaped files is larger than 8 pages,
this problem does not arise.
The attached code illustrates the problem.
Is this a bug in the OS or is there something wrong in my code ?
Sumit
[
segv_test.c 2K ]
/***
NAME
segv_test.c
PURPOSE
to test the mmap/mprotect problem on Solaris 2.5.1
compile:
cc -o segv_test segv_test.c
run:
segv_test 2 -> gives SIGSEGV on the second read
segv_test 4 shadow -> NO SIGSEGV
segv_test 9 shadow -> gives SIGSEGV on the second read
NOTES
We are trying to implement a multithreaded DSM on Solaris 2.5.1.
HISTORY
sumit - Jan 8, 1998: Created.
***/
#include <sys/mman.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
main(int argc, char **argv)
{
int fd;
int size;
char *base_address;
int page_size;
char *zero_buf;
int dummy;
char filename[256];
page_size = (int)sysconf(_SC_PAGESIZE);
if(argc == 3)
{
size = page_size*atoi(argv[1]);
strcpy(filename,argv[2]);
printf("%d pages, mapping file: %s\n",size/page_size,filename);
}
else if(argc == 2){
size = page_size*atoi(argv[1]);
strcpy(filename,"/dev/zero");
printf("%d pages, anonymous mapping\n",size/page_size);
}
else{
size = 2*page_size;
printf("%d pages, anonymous mapping\n",size/page_size);
}
if((fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0644)) < 0)
{
perror(filename);
exit(-1);
}
printf("allocating Zero_Buf\n");
if((zero_buf = calloc(size,1))==NULL)
{
perror("zero-buf");
exit(-2);
}
printf("writing %d bytes to %s\n",size,filename);
if(write(fd,zero_buf,size) <0)
{
perror("writing");
exit(-3);
}
printf("mmaping %s\n",filename);
if((base_address = mmap(0,size,PROT_NONE,MAP_SHARED,fd,0))<0){
perror("mmap");
exit(-4);
}
printf("mprotecting %d bytes, starting at %#08x\n",size, base_address);
mprotect(base_address, size, PROT_NONE);
printf("setting %d byte, starting at %#08x readable\n",1, base_address);
mprotect(base_address, 1, PROT_READ);
printf("reading from %#08x\n", base_address);
dummy = (int)(*base_address);
printf("type any key to continue\n");
gets(filename);
printf("reading from %#08x\n", base_address+size-1);
printf("type any key to continue\n");
gets(filename);
dummy = (int)(*(base_address+size-1));
Quote:}