mprotect problems with mmaped files in Solaris 2.5.1

mprotect problems with mmaped files in Solaris 2.5.1

Post by Sumit Ro » Fri, 09 Jan 1998 04:00:00



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:}

 
 
 

mprotect problems with mmaped files in Solaris 2.5.1

Post by Sven Pa » Sat, 10 Jan 1998 04:00:00


Hi,

: Is this a bug in the OS or is there something wrong in my code ?

We encountered the same problem while porting our
shared virtual memory system SVMlib from NT to Solaris.

We found that the error disappears if we try to map a file
which is located on a NFS-filesystem. This is, of course, no solution
but it is a workaround.

I had countact with some engineers from SUN. We suggest it's an
error in the implementation of the Solaris filesystem code.
Solaris SPARC performs a 32 KB read-ahead on files, that's just
8 pages of virtual memory. After the read-ahead, protection bits
are obviously not properly restored for the next 7 pages.

Just try to submit a formal bug report to SUN. It's an * OS bug.

Sven

--
|  _     :  Sven M. Paas, Lehrstuhl fuer Betriebssysteme (LfBS)
|_|_`__  :  RWTH Aachen,  Kopernikusstr. 16,  D-52056 Aachen
  | |__) :  Tel.  :  +49-241-80-5162,  Fax: +49-241-8888-339


 
 
 

mprotect problems with mmaped files in Solaris 2.5.1

Post by Casper H.S. Dik - Network Security Engine » Sun, 11 Jan 1998 04:00:00


[[ PLEASE DON'T SEND ME EMAIL COPIES OF POSTINGS ]]


>We found that the error disappears if we try to map a file
>which is located on a NFS-filesystem. This is, of course, no solution
>but it is a workaround.

You could also use tmpfs (but that isn't persitent across reboots)

Quote:>I had countact with some engineers from SUN. We suggest it's an
>error in the implementation of the Solaris filesystem code.
>Solaris SPARC performs a 32 KB read-ahead on files, that's just
>8 pages of virtual memory. After the read-ahead, protection bits
>are obviously not properly restored for the next 7 pages.
>Just try to submit a formal bug report to SUN. It's an * OS bug.

One has been submitted. The id is: 4102958.

I'm not sure if the read ahead really has much to do with it.

On the Ultra the problem also occurs with 8 pages, but the pages are
twice as long (I don't think there's a 64K read ahead involved on the
Ultra)

It also seems to be a SAPRC specific problem, one that doesn't appear to be
hardware releated (as the same code does work on SunOS 4.x).

Casper
--
Expressed in this posting are my opinions.  They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.

 
 
 

1. PROBLEM WITH MPROTECT (OR MMAP) MY SYSYEM CRASH !!!

I have an dynamic library and link single program (Hello World) with It.
When It starts run, I ummap all code and data, for make a memory access
monitor. How the init function is into shared lib, the memory is not the
same that main program (I have checked it in /proc ...). When I unmap
(or mprotect( dir , PROT_NONE ) ) my program crash ... and LINUX with it
(I need reinstall some packages, so each probe is mortal).

If a dlopen is made, you can unmap and mprotect all his regions.

This is my code:

// It executes before main ...
void init( void ) __attribute__ (( constructor )) ;

void init( void )
{
  struct sigaction act ;
  struct sigaction new_signal ;
  void *c_ini , *c_fin , *d_ini , *d_fin ;

  // FIRST : INSTALL SIGNALS
  new_signal.sa_handler = trat_segv ;
  sigaddset( &new_signal.sa_mask , SIGSEGV ) ;
  sigaddset( &new_signal.sa_mask , SIGALRM ) ;
  new_signal.sa_flags   = SA_RESTART | SA_NOCLDSTOP  ;
  sigaction( SIGSEGV , &new_signal , NULL ) ;

   // This funtion works. It obtains region of code and data directions.
   // c_ini = code_initial_direction
   // d_ini = data_initial_direction
   // c_fin = code_final_direction
   // d_fin = data_final_direction
   obtain_regions( prog_name , &c_ini , &c_fin , &d_ini , &d_fin ) ;

   // THE REGIONS AT THIS POINT ARE WELL OBTAINED AND DIRECTION OF PC IS
NOT
   // THE SAME AS ANY PAGE OF REGIONS.

   // PROGRAM CRASH IN THE NEXT LINE
   munmap( c_ini , ((unsigned int)c_fin - ((unsigned int)c_ini)) ) ;
   munmap( d_ini , ((unsigned int)d_fin - ((unsigned int)d_ini)) ) ;
   ...

? What can I make munmap ?
? Is there any manner of map a program frame into my memory address ?

Thaks,
DTM

2. X wont work with IBM PS/VP

3. MMAP AND MPROTECT

4. Linux User Group in Sacramento, CA?

5. mmap and mprotect

6. CATIA on RS/6000

7. mmap and mprotect.

8. Umax C500 wont install R5

9. Oracle8i on Solaris Intel - mprotect failed error

10. MMAP cache problem in 2.4.x, Re: [parisc-linux] unreliable mmap (fwd)

11. apache 1.3.3, solaris 2.6 and mmap'ing big files (~50MB)

12. commiting less than 64K for mmap'ed files on Solaris???

13. apache solaris "mmap: bad file number"