From cae87e64dca14f50da7bbd99085c7f5e413ad0f8 Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Mon, 13 Nov 2017 17:55:12 +0100 Subject: [PATCH] support: Add Based on the implementation in resolv/tst-inet_pton.c. --- ChangeLog | 8 +++++ resolv/tst-inet_pton.c | 67 +++++++---------------------------------- support/Makefile | 1 + support/next_to_fault.c | 52 ++++++++++++++++++++++++++++++++ support/next_to_fault.h | 48 +++++++++++++++++++++++++++++ 5 files changed, 120 insertions(+), 56 deletions(-) create mode 100644 support/next_to_fault.c create mode 100644 support/next_to_fault.h diff --git a/ChangeLog b/ChangeLog index 7482e6d348..ffeb208132 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2017-11-13 Florian Weimer + + * support/next_to_fault.h, support/next_to_fault.c: New files. + * support/Makefile (libsupport-routines): Add next_to_fault. + * resolv/tst-inet_pton.c (struct next_to_fault) + (next_to_fault_allocate, next_to_fault_free): Remove. + (run_one_test): Switch to interfaces. + 2017-11-13 H.J. Lu * elf/dl-support.c: Include . diff --git a/resolv/tst-inet_pton.c b/resolv/tst-inet_pton.c index 4bb9f81193..5a06a802b3 100644 --- a/resolv/tst-inet_pton.c +++ b/resolv/tst-inet_pton.c @@ -22,57 +22,10 @@ #include #include #include +#include #include -#include -#include #include -/* Memory region created by next_to_fault_allocate. */ -struct next_to_fault -{ - /* The user data. */ - char *buffer; - size_t length; - - /* The entire allocated region. */ - void *region_start; - size_t region_size; -}; - -/* Allocate a buffer of SIZE bytes just before a page which is mapped - with PROT_NONE (so that overrunning the buffer will cause a - fault). */ -static struct next_to_fault -next_to_fault_allocate (size_t size) -{ - long page_size = sysconf (_SC_PAGE_SIZE); - TEST_VERIFY_EXIT (page_size > 0); - struct next_to_fault result; - result.region_size = roundup (size, page_size) + page_size; - TEST_VERIFY_EXIT (size + page_size > size); - TEST_VERIFY_EXIT (result.region_size > 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; -} - -/* Deallocate the memory region allocated by - next_to_fault_allocate. */ -static void -next_to_fault_free (struct next_to_fault *ntf) -{ - xmunmap (ntf->region_start, ntf->region_size); - *ntf = (struct next_to_fault) { NULL, }; -} - struct test_case { /* The input data. */ @@ -139,12 +92,13 @@ run_one_test (const struct test_case *t) { size_t test_len = strlen (t->input); - struct next_to_fault ntf_out4 = next_to_fault_allocate (4); - struct next_to_fault ntf_out6 = next_to_fault_allocate (16); + struct support_next_to_fault ntf_out4 = support_next_to_fault_allocate (4); + struct support_next_to_fault ntf_out6 = support_next_to_fault_allocate (16); /* inet_pton requires NUL termination. */ { - struct next_to_fault ntf_in = next_to_fault_allocate (test_len + 1); + struct support_next_to_fault ntf_in + = support_next_to_fault_allocate (test_len + 1); memcpy (ntf_in.buffer, t->input, test_len + 1); memset (ntf_out4.buffer, 0, 4); check_result ("inet_pton", t, AF_INET, ntf_out4.buffer, @@ -152,12 +106,13 @@ run_one_test (const struct test_case *t) memset (ntf_out6.buffer, 0, 16); check_result ("inet_pton", t, AF_INET6, ntf_out6.buffer, inet_pton (AF_INET6, ntf_in.buffer, ntf_out6.buffer)); - next_to_fault_free (&ntf_in); + support_next_to_fault_free (&ntf_in); } /* __inet_pton_length does not require NUL termination. */ { - struct next_to_fault ntf_in = next_to_fault_allocate (test_len); + struct support_next_to_fault ntf_in + = support_next_to_fault_allocate (test_len); memcpy (ntf_in.buffer, t->input, test_len); memset (ntf_out4.buffer, 0, 4); check_result ("__inet_pton_length", t, AF_INET, ntf_out4.buffer, @@ -167,11 +122,11 @@ run_one_test (const struct test_case *t) check_result ("__inet_pton_length", t, AF_INET6, ntf_out6.buffer, __inet_pton_length (AF_INET6, ntf_in.buffer, ntf_in.length, ntf_out6.buffer)); - next_to_fault_free (&ntf_in); + support_next_to_fault_free (&ntf_in); } - next_to_fault_free (&ntf_out4); - next_to_fault_free (&ntf_out6); + support_next_to_fault_free (&ntf_out4); + support_next_to_fault_free (&ntf_out6); } /* The test cases were manually crafted and the set enhanced with diff --git a/support/Makefile b/support/Makefile index dafb1737a4..f7a878b950 100644 --- a/support/Makefile +++ b/support/Makefile @@ -32,6 +32,7 @@ libsupport-routines = \ check_netent \ delayed_exit \ ignore_stderr \ + next_to_fault \ oom_error \ resolv_test \ set_fortify_handler \ 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 + . */ + +#include +#include +#include +#include +#include + +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, }; +} diff --git a/support/next_to_fault.h b/support/next_to_fault.h new file mode 100644 index 0000000000..dd71c28ac0 --- /dev/null +++ b/support/next_to_fault.h @@ -0,0 +1,48 @@ +/* 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 + . */ + +#ifndef SUPPORT_NEXT_TO_FAULT_H +#define SUPPORT_NEXT_TO_FAULT_H + +#include +#include + +__BEGIN_DECLS + +/* The memory region created by next_to_fault_allocate. */ +struct support_next_to_fault +{ + /* The user data. */ + char *buffer; + size_t length; + + /* The entire allocated region. */ + void *region_start; + size_t region_size; +}; + +/* Allocate a buffer of SIZE bytes just before a page which is mapped + with PROT_NONE (so that overrunning the buffer will cause a + fault). */ +struct support_next_to_fault support_next_to_fault_allocate (size_t size); + +/* Deallocate the memory region allocated by + next_to_fault_allocate. */ +void support_next_to_fault_free (struct support_next_to_fault *); + +#endif /* SUPPORT_NEXT_TO_FAULT_H */