diff options
author | Yann Ylavic <ylavic@apache.org> | 2021-03-02 00:37:18 +0000 |
---|---|---|
committer | Yann Ylavic <ylavic@apache.org> | 2021-03-02 00:37:18 +0000 |
commit | 17f630750e9e5a40872d8c8c3a48622ed9244d53 (patch) | |
tree | a9497308b9bb36677fbb9827617ff237287d6c8c /mmap | |
parent | 58126550800e0fd66790d216394e61772f329e6c (diff) | |
download | apr-17f630750e9e5a40872d8c8c3a48622ed9244d53.tar.gz |
Align apr_mmap()ing offset to a page boundary. PR 65158.
This is requirement for unix systems, and otherwise can cause failures or
undefined behaviour with some filesystems.
Add apr_mmap_t->poffset on unixes to track the offset to the previous page,
relative to the user requested/actual offset. This allows ->mm and ->size to
still point to the actual data, while munmap() still deletes the full range
from the start of the page.
Tests updated accordingly.
git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1887060 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'mmap')
-rw-r--r-- | mmap/unix/mmap.c | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/mmap/unix/mmap.c b/mmap/unix/mmap.c index 671957096..48b881332 100644 --- a/mmap/unix/mmap.c +++ b/mmap/unix/mmap.c @@ -14,6 +14,8 @@ * limitations under the License. */ +#include <assert.h> + #include "apr.h" #include "apr_private.h" #include "apr_general.h" @@ -33,6 +35,9 @@ #if APR_HAVE_STDIO_H #include <stdio.h> #endif +#if APR_HAVE_UNISTD_H +#include <unistd.h> /* for sysconf() */ +#endif #ifdef HAVE_SYS_STAT_H #include <sys/stat.h> #endif @@ -61,7 +66,7 @@ static apr_status_t mmap_cleanup(void *themmap) #ifdef BEOS rv = delete_area(mm->area); #else - rv = munmap(mm->mm, mm->size); + rv = munmap((char *)mm->mm - mm->poffset, mm->size + mm->poffset); #endif mm->mm = (void *)-1; @@ -81,6 +86,8 @@ APR_DECLARE(apr_status_t) apr_mmap_create(apr_mmap_t **new, area_id aid = -1; uint32 pages = 0; #else + static long psize; + apr_off_t poffset = 0; apr_int32_t native_flags = 0; #endif @@ -130,7 +137,18 @@ APR_DECLARE(apr_status_t) apr_mmap_create(apr_mmap_t **new, native_flags |= PROT_READ; } - mm = mmap(NULL, size, native_flags, MAP_SHARED, file->filedes, offset); +#if defined(_SC_PAGESIZE) + if (psize == 0) { + psize = sysconf(_SC_PAGESIZE); + /* the page size should be a power of two */ + assert(psize > 0 && (psize & (psize - 1)) == 0); + } + poffset = offset & (apr_off_t)(psize - 1); +#endif + + mm = mmap(NULL, size + poffset, + native_flags, MAP_SHARED, + file->filedes, offset - poffset); if (mm == (void *)-1) { /* we failed to get an mmap'd file... */ @@ -139,7 +157,8 @@ APR_DECLARE(apr_status_t) apr_mmap_create(apr_mmap_t **new, } #endif - (*new)->mm = mm; + (*new)->mm = (char *)mm + poffset; + (*new)->poffset = poffset; (*new)->size = size; (*new)->cntxt = cont; APR_RING_ELEM_INIT(*new, link); |