Bruce Korb wrote:
> txtmi->txt_data = mmap (NULL, txtmi->txt_size, prot, flags, txtmi->txt_fd,
> 0);
...
> /*
> * Still here? We have to append a page of NUL's
> */
> txtmi->txt_full_size += pgsz;
> {
> void* pNuls;
>
> #ifdef MAP_ANONYMOUS
> pNuls = mmap ((void*)(((char*)txtmi->txt_data) + txtmi->txt_size), pgsz,
> PROT_READ, MAP_SHARED|MAP_ANONYMOUS|MAP_FIXED, 0, 0);
> #else
> txtmi->txt_zero_fd = open ("/dev/zero", O_RDONLY);
> if (txtmi->txt_zero_fd < 0)
> pNuls = MAP_FAILED;
>
> else pNuls =
> mmap ((void*)(((char*)txtmi->txt_data) + txtmi->txt_size), pgsz,
> PROT_READ, MAP_PRIVATE|MAP_FIXED, txtmi->txt_zero_fd, 0);
> #endif
>
> /*
> * If we couldn't map the page of NULs, then the caller can
> * figure this out by checking that full_size == size and
> * the txt_errno is not zero.
> */
> if (pNuls == MAP_FAILED) {
> txtmi->txt_errno = errno;
> txtmi->txt_full_size = txtmi->txt_size;
> }
This is not reliable. You have no guarantee that a page will be available
after the area covered by the first mmap. If you're unlucky, the second
mmap will supersede a block allocated by malloc or the text segment of a
shared library.
To do it correctly, you need
- first, an anonymous mmap of the entire address range at once,
- then, mmap the file with MAP_FIXED to the first portion of this range.
Bruno