1 /* Memory allocation next to an unmapped page.
2    Copyright (C) 2017-2022 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4 
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9 
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
18 
19 #include <support/check.h>
20 #include <support/next_to_fault.h>
21 #include <support/xunistd.h>
22 #include <sys/mman.h>
23 #include <sys/param.h>
24 
25 struct support_next_to_fault
support_next_to_fault_allocate(size_t size)26 support_next_to_fault_allocate (size_t size)
27 {
28   long page_size = sysconf (_SC_PAGE_SIZE);
29   TEST_VERIFY_EXIT (page_size > 0);
30   struct support_next_to_fault result;
31   result.region_size = roundup (size, page_size) + page_size;
32   if (size + page_size <= size || result.region_size <= size)
33     FAIL_EXIT1 ("support_next_to_fault_allocate (%zu): overflow", size);
34   result.region_start
35     = xmmap (NULL, result.region_size, PROT_READ | PROT_WRITE,
36              MAP_PRIVATE | MAP_ANONYMOUS, -1);
37   /* Unmap the page after the allocation.  */
38   xmprotect (result.region_start + (result.region_size - page_size),
39              page_size, PROT_NONE);
40   /* Align the allocation within the region so that it ends just
41      before the PROT_NONE page.  */
42   result.buffer = result.region_start + result.region_size - page_size - size;
43   result.length = size;
44   return result;
45 }
46 
47 void
support_next_to_fault_free(struct support_next_to_fault * ntf)48 support_next_to_fault_free (struct support_next_to_fault *ntf)
49 {
50   xmunmap (ntf->region_start, ntf->region_size);
51   *ntf = (struct support_next_to_fault) { NULL, };
52 }
53