summaryrefslogtreecommitdiff
path: root/mmap
diff options
context:
space:
mode:
authorYann Ylavic <ylavic@apache.org>2021-03-02 00:37:18 +0000
committerYann Ylavic <ylavic@apache.org>2021-03-02 00:37:18 +0000
commit17f630750e9e5a40872d8c8c3a48622ed9244d53 (patch)
treea9497308b9bb36677fbb9827617ff237287d6c8c /mmap
parent58126550800e0fd66790d216394e61772f329e6c (diff)
downloadapr-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.c25
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);