summaryrefslogtreecommitdiff
path: root/support/next_to_fault.c
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2017-11-13 17:55:12 +0100
committerFlorian Weimer <fweimer@redhat.com>2017-11-13 19:29:32 +0100
commitcae87e64dca14f50da7bbd99085c7f5e413ad0f8 (patch)
tree685bd105721f6f2f8ccc764f2a9a7569b70cdb63 /support/next_to_fault.c
parenteceed67166ca9ee0587107baa394c7c3bc369813 (diff)
support: Add <support/next_to_fault.h>
Based on the implementation in resolv/tst-inet_pton.c.
Diffstat (limited to 'support/next_to_fault.c')
-rw-r--r--support/next_to_fault.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/support/next_to_fault.c b/support/next_to_fault.c
new file mode 100644
index 0000000000..7c6b077898
--- /dev/null
+++ b/support/next_to_fault.c
@@ -0,0 +1,52 @@
+/* Memory allocation next to an unmapped page.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <support/check.h>
+#include <support/next_to_fault.h>
+#include <support/xunistd.h>
+#include <sys/mman.h>
+#include <sys/param.h>
+
+struct support_next_to_fault
+support_next_to_fault_allocate (size_t size)
+{
+ long page_size = sysconf (_SC_PAGE_SIZE);
+ TEST_VERIFY_EXIT (page_size > 0);
+ struct support_next_to_fault result;
+ result.region_size = roundup (size, page_size) + page_size;
+ if (size + page_size <= size || result.region_size <= size)
+ FAIL_EXIT1 ("support_next_to_fault_allocate (%zu): overflow", size);
+ result.region_start
+ = xmmap (NULL, result.region_size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1);
+ /* Unmap the page after the allocation. */
+ xmprotect (result.region_start + (result.region_size - page_size),
+ page_size, PROT_NONE);
+ /* Align the allocation within the region so that it ends just
+ before the PROT_NONE page. */
+ result.buffer = result.region_start + result.region_size - page_size - size;
+ result.length = size;
+ return result;
+}
+
+void
+support_next_to_fault_free (struct support_next_to_fault *ntf)
+{
+ xmunmap (ntf->region_start, ntf->region_size);
+ *ntf = (struct support_next_to_fault) { NULL, };
+}