elf: Add tests for working RELRO protection
Commit Message
* Carlos O'Donell:
>> + /* Check that a fault only at the second byte results in an error.
>> + Again, the probe range crosses a page boundary. */
>
> Should this say "Check that a *missing* fault only at the ... " ?
>
>> + is_failed = support_record_failure_is_failed ();
>> + {
>> + char *ptr = xmmap (NULL, 2 * page_size, PROT_READ | PROT_WRITE,
>> + MAP_PRIVATE | MAP_ANONYMOUS, -1);
>> + xmprotect (ptr + page_size, page_size, PROT_READ);
The second page is made read-only here, corresponding the the second
byte. This means that the fault is missing for the first byte, not the
second.
>> +#include <support/support.h>
>> +
>> +void
>> +support_disable_more_coredumps (void)
>> +{
>> + /* Hurd does not have any additional coredumps to disable. */
>> +}
>>
>
> OK. This fixes the prctl issue. Looks like you ran bmg? ;-)
I did, but I may have fixed this proactively. I'm getting better at
porting to Hurd.
> It is odd to have a file that is for support/* but is outside of
> support/*.
On the other hand, it's how sysdeps overrides work.
New patch depending on dlinfo_soname below.
Thanks,
Florian
8<-------------------------------------------------------------------->8
Subject: elf: Add tests for working RELRO protection
-----
2019-10-02 Florian Weimer <fweimer@redhat.com>
elf: Add tests for working RELRO protection.
* elf/Makefile [$(build-shared)] (tests): Add tst-relro-shared,
tst-relro-static, tst-relro-dlopen.
[$(have-fpie) && $(build-shared)] (tests, tests-pie): Add
tst-relro-shared-pie.
(tst-relro-shared, tst-relro-shared-pie): Link with -ldl.
(LDFLAGS-tst-relro-shared, LDFLAGS-tst-relro-shared-pie): Link
with -z relro.
(tst-relro-shared-no-pie): Set to disable PIE for
tst-relro-shared.
(CFLAGS-tst-relro-shared-pie.c): Build with -fpie.
* elf/tst-relro.h: New file.
* elf/tst-relro-shared.c: Likewise.
* elf/tst-relro-shared-pie.c: Likewise.
* elf/tst-relro-static.c: Likewise.
* elf/tst-relro-static-dlopen.c: Likewise.
* support/Makefile (libsupport-routines): Add
support_disable_more_coredumps, support_check_fault_write.
(tests): Add tst-support_check_fault.
* support/support.h (support_disable_more_coredumps): Declare.
* support/check_fault.h: New file.
* support/support_check_fault_write.c: Likewise.
* support/support_disable_more_coredumps.c: Likewise.
* support/tst-support_check_fault.c: Likewise.
* sysdeps/mach/hurd/support_disable_more_coredumps.c: Likewise.
Comments
On 07/10/2019 11:45, Florian Weimer wrote:
> * Carlos O'Donell:
>
>>> + /* Check that a fault only at the second byte results in an error.
>>> + Again, the probe range crosses a page boundary. */
>>
>> Should this say "Check that a *missing* fault only at the ... " ?
>>
>>> + is_failed = support_record_failure_is_failed ();
>>> + {
>>> + char *ptr = xmmap (NULL, 2 * page_size, PROT_READ | PROT_WRITE,
>>> + MAP_PRIVATE | MAP_ANONYMOUS, -1);
>>> + xmprotect (ptr + page_size, page_size, PROT_READ);
>
> The second page is made read-only here, corresponding the the second
> byte. This means that the fault is missing for the first byte, not the
> second.
>
>>> +#include <support/support.h>
>>> +
>>> +void
>>> +support_disable_more_coredumps (void)
>>> +{
>>> + /* Hurd does not have any additional coredumps to disable. */
>>> +}
>>>
>>
>> OK. This fixes the prctl issue. Looks like you ran bmg? ;-)
>
> I did, but I may have fixed this proactively. I'm getting better at
> porting to Hurd.
>
>> It is odd to have a file that is for support/* but is outside of
>> support/*.
>
> On the other hand, it's how sysdeps overrides work.
>
> New patch depending on dlinfo_soname below.
>
> Thanks,
> Florian
>
> 8<-------------------------------------------------------------------->8
> Subject: elf: Add tests for working RELRO protection
Patch looks good in general, however both tests below fail with
--enable-static-pie:
FAIL: elf/tst-relro-static
FAIL: elf/tst-relro-static-dlopen
But these are fixed by my "elf: Enable relro for static build" patch
[1], so I don't see this as a blocker.
I also it would be good to add some checks for variables created
with __attribute__ ((section (".data.rel.ro"))) on main executable,
but I don't see this as a blocker either.
And I have reviewed both the required patches for this [1] [2],
so I think we move forward on my vDSO refactor.
[1] https://sourceware.org/ml/libc-alpha/2019-12/msg00454.html
[2] https://sourceware.org/ml/libc-alpha/2019-12/msg00547.html
[3] https://sourceware.org/ml/libc-alpha/2019-12/msg00550.html
>
> -----
> 2019-10-02 Florian Weimer <fweimer@redhat.com>
>
> elf: Add tests for working RELRO protection.
> * elf/Makefile [$(build-shared)] (tests): Add tst-relro-shared,
> tst-relro-static, tst-relro-dlopen.
> [$(have-fpie) && $(build-shared)] (tests, tests-pie): Add
> tst-relro-shared-pie.
> (tst-relro-shared, tst-relro-shared-pie): Link with -ldl.
> (LDFLAGS-tst-relro-shared, LDFLAGS-tst-relro-shared-pie): Link
> with -z relro.
> (tst-relro-shared-no-pie): Set to disable PIE for
> tst-relro-shared.
> (CFLAGS-tst-relro-shared-pie.c): Build with -fpie.
> * elf/tst-relro.h: New file.
> * elf/tst-relro-shared.c: Likewise.
> * elf/tst-relro-shared-pie.c: Likewise.
> * elf/tst-relro-static.c: Likewise.
> * elf/tst-relro-static-dlopen.c: Likewise.
> * support/Makefile (libsupport-routines): Add
> support_disable_more_coredumps, support_check_fault_write.
> (tests): Add tst-support_check_fault.
> * support/support.h (support_disable_more_coredumps): Declare.
> * support/check_fault.h: New file.
> * support/support_check_fault_write.c: Likewise.
> * support/support_disable_more_coredumps.c: Likewise.
> * support/tst-support_check_fault.c: Likewise.
> * sysdeps/mach/hurd/support_disable_more_coredumps.c: Likewise.>
> diff --git a/elf/Makefile b/elf/Makefile
> index dea51ca182..bea384efdc 100644
> --- a/elf/Makefile
> +++ b/elf/Makefile
> @@ -148,7 +148,8 @@ endif
> tests-static-normal := tst-leaks1-static tst-array1-static tst-array5-static \
> tst-dl-iter-static \
> tst-tlsalign-static tst-tlsalign-extern-static \
> - tst-linkall-static tst-env-setuid tst-env-setuid-tunables
> + tst-linkall-static tst-env-setuid tst-env-setuid-tunables \
> + tst-relro-static tst-relro-static-dlopen
> tests-static-internal := tst-tls1-static tst-tls2-static \
> tst-ptrguard1-static tst-stackguard1-static \
> tst-tls1-static-non-pie tst-libc_dlvsym-static
Ok.
> @@ -192,7 +193,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
> tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose \
> tst-debug1 tst-main1 tst-absolute-sym tst-absolute-zero tst-big-note \
> tst-unwind-ctor tst-unwind-main tst-audit13 \
> - tst-sonamemove-link tst-sonamemove-dlopen tst-dlopen-aout
> + tst-sonamemove-link tst-sonamemove-dlopen tst-dlopen-aout \
> + tst-relro-shared
> # reldep9
> tests-internal += loadtest unload unload2 circleload1 \
> neededtest neededtest2 neededtest3 neededtest4 \
Ok.
> @@ -308,8 +310,9 @@ test-xfail-tst-protected1b = yes
> endif
> ifeq (yesyes,$(have-fpie)$(build-shared))
> modules-names += tst-piemod1
> -tests += tst-pie1 tst-pie2 tst-dlopen-pie tst-dlopen-aout-pie
> -tests-pie += tst-pie1 tst-pie2 tst-dlopen-aout-pie
> +tests += tst-pie1 tst-pie2 tst-dlopen-pie tst-dlopen-aout-pie \
> + tst-relro-shared-pie
> +tests-pie += tst-pie1 tst-pie2 tst-dlopen-aout-pie tst-relro-shared-pie
> ifeq (yes,$(have-protected-data))
> tests += vismain
> tests-pie += vismain
Ok.
> @@ -1274,6 +1277,15 @@ CFLAGS-tst-dlopen-aout-pie.c += $(pie-ccflag)
> $(objpfx)tst-dlopen-aout-pie: $(libdl) $(shared-thread-library)
> $(objpfx)tst-dlopen-aout-container: $(libdl) $(shared-thread-library)
> LDFLAGS-tst-dlopen-aout-container += -Wl,-rpath,\$$ORIGIN
> +$(objpfx)tst-relro-shared: $(libdl)
> +LDFLAGS-tst-relro-shared += $(relro-LDFLAGS)
> +tst-relro-shared-no-pie = yes
> +CFLAGS-tst-relro-shared-pie.c += $(pie-ccflag)
> +$(objpfx)tst-relro-shared-pie: $(libdl)
> +LDFLAGS-tst-relro-shared-pie += $(relro-LDFLAGS)
> +tst-relro-static-dlopen-ENV = \
> + LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)dlfcn
> +$(objpfx)tst-relro-static-dlopen: $(common-objpfx)dlfcn/libdl.a
>
> CFLAGS-ifuncmain1pic.c += $(pic-ccflag)
> CFLAGS-ifuncmain1picstatic.c += $(pic-ccflag)
Ok.
Does it need to add full RELRO (enabled with -Wl,-z,now) tests as well?
> diff --git a/elf/tst-relro-shared-pie.c b/elf/tst-relro-shared-pie.c
> new file mode 100644
> index 0000000000..64f3dfcf45
> --- /dev/null
> +++ b/elf/tst-relro-shared-pie.c
> @@ -0,0 +1,19 @@
> +/* Test that RELRO is applied to the program, ld.so, libc.so. PIE version.
> + Copyright (C) 2019 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
> + <https://www.gnu.org/licenses/>. */
> +
> +#include "tst-relro-shared.c"
Ok.
> diff --git a/elf/tst-relro-shared.c b/elf/tst-relro-shared.c
> new file mode 100644
> index 0000000000..1265125917
> --- /dev/null
> +++ b/elf/tst-relro-shared.c
> @@ -0,0 +1,50 @@
> +/* Test that RELRO protection is applied to the program, ld.so, libc.so.
> + Copyright (C) 2019 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
> + <https://www.gnu.org/licenses/>. */
> +
> +#include <gnu/lib-names.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <support/check_fault.h>
> +#include <support/xdlfcn.h>
> +
> +#include "tst-relro.h"
> +
> +static void (*const global_function_pointer) (void *) = free;
> +
> +static int
> +do_test (void)
> +{
> + printf ("info: checking global_function_pointer (%p)\n",
> + &global_function_pointer);
> + support_check_fault_write (&global_function_pointer,
> + sizeof (global_function_pointer));
> +
> + check_relro_symbol (NULL, "_rtld_global_ro", LD_SO);
> + check_relro_symbol (NULL, "_nl_default_dirname", LIBC_SO);
> +
> + /* Load libc.so into a new namespace and check that as well. */
> + void *new_libc = xdlmopen (LM_ID_NEWLM, LIBC_SO, RTLD_NOW);
> + check_relro_symbol (new_libc, "_rtld_global_ro", LD_SO);
> + check_relro_symbol (new_libc, "_nl_default_dirname", LIBC_SO);
> +
> + xdlclose (new_libc);
> +
> + return 0;
> +}
> +
> +#include <support/test-driver.c>
Ok.
> diff --git a/elf/tst-relro-static-dlopen.c b/elf/tst-relro-static-dlopen.c
> new file mode 100644
> index 0000000000..56fa20cc00
> --- /dev/null
> +++ b/elf/tst-relro-static-dlopen.c
> @@ -0,0 +1,45 @@
> +/* Test RELRO protection in a statically linked program, with dlopen.
> + Copyright (C) 2019 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
> + <https://www.gnu.org/licenses/>. */
> +
> +#include <gnu/lib-names.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <support/check_fault.h>
> +#include <support/xdlfcn.h>
> +
> +#include "tst-relro.h"
> +
> +static void (*const global_function_pointer) (void *) = free;
> +
> +static int
> +do_test (void)
> +{
> + printf ("info: checking global_function_pointer (%p)\n",
> + &global_function_pointer);
> + support_check_fault_write (&global_function_pointer,
> + sizeof (global_function_pointer));
> +
> + void *libc = xdlopen (LIBC_SO, RTLD_NOW);
> + check_relro_symbol (libc, "_rtld_global_ro", LD_SO);
> + check_relro_symbol (libc, "_nl_default_dirname", LIBC_SO);
> + xdlclose (libc);
> +
> + return 0;
> +}
> +
> +#include <support/test-driver.c>
Ok.
> diff --git a/elf/tst-relro-static.c b/elf/tst-relro-static.c
> new file mode 100644
> index 0000000000..8479073a40
> --- /dev/null
> +++ b/elf/tst-relro-static.c
> @@ -0,0 +1,35 @@
> +/* Test RELRO protection in a statically linked program.
> + Copyright (C) 2019 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
> + <https://www.gnu.org/licenses/>. */
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <support/check_fault.h>
> +
> +static void (*const global_function_pointer) (void *) = free;
> +
> +static int
> +do_test (void)
> +{
> + printf ("info: checking global_function_pointer (%p)\n",
> + &global_function_pointer);
> + support_check_fault_write (&global_function_pointer,
> + sizeof (global_function_pointer));
> + return 0;
> +}
> +
> +#include <support/test-driver.c>
Ok.
> diff --git a/elf/tst-relro.h b/elf/tst-relro.h
> new file mode 100644
> index 0000000000..0c86c4be1b
> --- /dev/null
> +++ b/elf/tst-relro.h
> @@ -0,0 +1,44 @@
> +/* Support code for testing RELRO protection.
> + Copyright (C) 2019 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
> + <https://www.gnu.org/licenses/>. */
> +
> +#include <support/xdlfcn.h>
> +#include <support/check.h>
> +#include <support/check_fault.h>
> +#include <stdio.h>
> +
> +/* Check that the symbol NAME in HANDLE (which can be null) is not
> + located in writable memory. The corresponding address must be
> + located in the shared object with soname equal to EXPECTED_SONAME.
> +
> + This function uses dlsym to avoid introducing copy relocations,
> + rather than accepting the pointer directly. Otherwise, the test
> + exercises RELRO protection in a different object. */
> +static void
> +check_relro_symbol (void *handle, const char *name,
> + const char *expected_soname)
> +{
> + void *ptr = xdlsym (handle, name);
> + printf ("info: checking symbol %s in DSO %s at %p (handle %p)\n",
> + name, expected_soname, ptr, handle);
> + support_check_fault_write (ptr, 1);
> + Dl_info info;
> + void *actual_handle;
> + if (dladdr1 (ptr, &info, &actual_handle, RTLD_DL_HANDLE) == 0)
> + FAIL_EXIT1 ("dladdr1 for %s in %s failed", name, expected_soname);
> + TEST_COMPARE_STRING (dlinfo_soname (actual_handle), expected_soname);
> +}
Ok, I had to track down there missing pieces to understanding from where
RTLD_DL_HANDLE and dlinfo_soname come from [1] [2].
[1] https://sourceware.org/ml/libc-alpha/2019-10/msg00111.html
> diff --git a/support/Makefile b/support/Makefile
> index ca238ee8b4..58ea1b974d 100644
> --- a/support/Makefile
> +++ b/support/Makefile
> @@ -43,10 +43,12 @@ libsupport-routines = \
> support_can_chroot \
> support_capture_subprocess \
> support_capture_subprocess_check \
> + support_check_fault_write \
> support_chroot \
> support_copy_file_range \
> support_descriptor_supports_holes \
> support_descriptors \
> + support_disable_more_coredumps \
> support_enter_mount_namespace \
> support_enter_network_namespace \
> support_format_address_family \
> @@ -218,6 +220,7 @@ tests = \
> tst-support-namespace \
> tst-support_blob_repeat \
> tst-support_capture_subprocess \
> + tst-support_check_fault \
> tst-support_descriptors \
> tst-support_format_dns_packet \
> tst-support_quote_blob \
Ok.
> diff --git a/support/check_fault.h b/support/check_fault.h
> new file mode 100644
> index 0000000000..03d5c7f41d
> --- /dev/null
> +++ b/support/check_fault.h
> @@ -0,0 +1,29 @@
> +/* Check for faults at specific addresses.
> + Copyright (C) 2019 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
> + <https://www.gnu.org/licenses/>. */
> +
> +#ifndef SUPPORT_CHECK_FAULT_H
> +#define SUPPORT_CHECK_FAULT_H
> +
> +#include <stddef.h>
> +
> +/* Check that write access to SIZE individual bytes starting at
> + address results in SIGSEGV or SIGBUS signal. Both signals must not
> + be blocked and must have SIG_DFL disposition. */
> +void support_check_fault_write (const void *address, size_t size);
> +
> +#endif /* SUPPORT_CHECK_FAULT_H */
Ok.
> diff --git a/support/support.h b/support/support.h
> index a9df6e9a3c..5677a8e682 100644
> --- a/support/support.h
> +++ b/support/support.h
> @@ -80,6 +80,11 @@ char *support_quote_string (const char *);
> regular file open for writing, and initially empty. */
> int support_descriptor_supports_holes (int fd);
>
> +/* For performance reasons, some tests need to disable all coredumps
> + (not just those which are written to the source directory, which
> + are disabled by the test driver). */
> +void support_disable_more_coredumps (void);
> +
> /* Error-checking wrapper functions which terminate the process on
> error. */
>
Ok.
> diff --git a/support/support_check_fault_write.c b/support/support_check_fault_write.c
> new file mode 100644
> index 0000000000..e3497863b6
> --- /dev/null
> +++ b/support/support_check_fault_write.c
> @@ -0,0 +1,72 @@
> +/* Check for faults at specific addresses.
> + Copyright (C) 2019 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
> + <https://www.gnu.org/licenses/>. */
> +
> +#include <support/check_fault.h>
> +
> +#include <signal.h>
> +#include <stdbool.h>
> +#include <stdio.h>
> +#include <support/check.h>
> +#include <support/support.h>
> +#include <support/xunistd.h>
> +#include <sys/wait.h>
> +#include <unistd.h>
> +
> +/* Probe once at ADDRESS. Use START and INDEX in error reporting. */
> +static bool
> +check_one_address (volatile char *address, const void *start, size_t index)
> +{
> + pid_t pid = xfork ();
> + if (pid == 0)
> + {
> + support_disable_more_coredumps ();
> + *address = 0xcc; /* Try to write an arbitrary value. */
> + _exit (0);
> + }
> + int status;
> + xwaitpid (pid, &status, 0);
> + if (WIFSIGNALED (status))
> + {
> + if (WTERMSIG (status) != SIGSEGV && WTERMSIG (status) != SIGBUS)
> + {
> + support_record_failure ();
> + printf ("error: unexpected signal %d at %p (%p+%zu)\n",
> + WTERMSIG (status), address, start, index);
> + return false;
> + }
> + }
> + else
> + {
> + support_record_failure ();
> + printf ("error: missing fault at %p (%p+%zu)\n",
> + address, start, index);
> + return false;
> + }
> + return true;
> +}
Maybe use support_capture_subprocess_check for this? We might need
to add another support_capture_subprocess_check variant to receive
a list of possible signals. Also, do we really need to check for
SIGBUS once the test is doing uint8_t access?
> +
> +void
> +support_check_fault_write (const void *address, size_t size)
> +{
> + TEST_VERIFY (address != NULL);
> + TEST_VERIFY (size > 0);
> +
> + for (size_t i = 0; i < size; ++i)
> + if (!check_one_address (((char *) address) + i, address, i))
> + break;
> +}
Ok.
> diff --git a/support/support_disable_more_coredumps.c b/support/support_disable_more_coredumps.c
> new file mode 100644
> index 0000000000..954f16027b
> --- /dev/null
> +++ b/support/support_disable_more_coredumps.c
> @@ -0,0 +1,28 @@
> +/* Disable additional coredumps. Version using <sys/prctl.h>.
> + Copyright (C) 2019 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
> + <https://www.gnu.org/licenses/>. */
> +
> +#include <support/check.h>
> +#include <support/support.h>
> +#include <sys/prctl.h>
> +
> +void
> +support_disable_more_coredumps (void)
> +{
> + if (prctl (PR_SET_DUMPABLE, 0, 0, 0, 0) != 0)
> + FAIL_EXIT1 ("prctl (PR_SET_DUMPABLE) failure: %m");
> +}
Ok.
> diff --git a/support/tst-support_check_fault.c b/support/tst-support_check_fault.c
> new file mode 100644
> index 0000000000..8a6b6d9825
> --- /dev/null
> +++ b/support/tst-support_check_fault.c
> @@ -0,0 +1,118 @@
> +/* Tests for support_fault_check_write.
> + Copyright (C) 2019 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
> + <https://www.gnu.org/licenses/>. */
> +
> +#include <support/check_fault.h>
> +
> +#include <array_length.h>
> +#include <stdlib.h>
> +#include <support/capture_subprocess.h>
> +#include <support/check.h>
> +#include <support/support.h>
> +#include <support/xunistd.h>
> +#include <sys/mman.h>
> +
> +static void
> +check_fault_two_bytes (void *address)
> +{
> + support_check_fault_write (address, 2);
> +}
> +
> +static int
> +do_test (void)
> +{
> + size_t page_size = xsysconf (_SC_PAGESIZE);
> +
> + /* Tests with PROT_NONE, PROT_READ and PROT_EXEC are expected to
> + succeed. */
> + {
> + static const int prots[] = { PROT_NONE, PROT_READ, PROT_EXEC };
> + for (int i = 0; i < array_length (prots); ++i)
> + {
> + void *ptr = xmmap (NULL, 2, prots[i], MAP_PRIVATE | MAP_ANONYMOUS, -1);
> + support_check_fault_write (ptr, 2);
> + xmunmap (ptr, 2);
> + }
> + }
Ok.
> +
> + /* Do not call support_record_failure_reset below if the process has
> + already failed. */
> + int is_failed = support_record_failure_is_failed ();
> +
> + /* Check that the lack of a fault for regular memory is reported at
> + the fist byte. */
> + {
> + void *ptr = xmalloc (2);
> + struct support_capture_subprocess proc
> + = support_capture_subprocess (check_fault_two_bytes, ptr);
> + support_capture_subprocess_check (&proc, "malloc", 0, sc_allow_stdout);
> + if (!is_failed)
> + support_record_failure_reset ();
> + char *expected = xasprintf ("error: missing fault at %p (%p+0)\n",
> + ptr, ptr);
> + TEST_COMPARE_STRING (proc.out.buffer, expected);
> + free (expected);
> + support_capture_subprocess_free (&proc);
> + free (ptr);
> + }
Ok.
> +
> + /* Check that a fault only at the first byte results in an error.
> + The probe range crosses a page boundary. */
> + is_failed = support_record_failure_is_failed ();
> + {
> + char *ptr = xmmap (NULL, 2 * page_size, PROT_READ | PROT_WRITE,
> + MAP_PRIVATE | MAP_ANONYMOUS, -1);
> + xmprotect (ptr, page_size, PROT_READ);
> + struct support_capture_subprocess proc
> + = support_capture_subprocess (check_fault_two_bytes,
> + ptr + page_size - 1);
> + support_capture_subprocess_check (&proc, "R, RW", 0, sc_allow_stdout);
> + if (!is_failed)
> + support_record_failure_reset ();
> + char *expected = xasprintf ("error: missing fault at %p (%p+1)\n",
> + ptr + page_size, ptr + page_size - 1);
> + TEST_COMPARE_STRING (proc.out.buffer, expected);
> + free (expected);
> + support_capture_subprocess_free (&proc);
> + xmunmap (ptr, 2 * page_size);
> + }
Ok.
> +
> + /* Check that a fault only at the second byte results in an error.
> + Again, the probe range crosses a page boundary. */
> + is_failed = support_record_failure_is_failed ();
> + {
> + char *ptr = xmmap (NULL, 2 * page_size, PROT_READ | PROT_WRITE,
> + MAP_PRIVATE | MAP_ANONYMOUS, -1);
> + xmprotect (ptr + page_size, page_size, PROT_READ);
> + struct support_capture_subprocess proc
> + = support_capture_subprocess (check_fault_two_bytes,
> + ptr + page_size - 1);
> + support_capture_subprocess_check (&proc, "RW, R", 0, sc_allow_stdout);
> + if (!is_failed)
> + support_record_failure_reset ();
> + char *expected = xasprintf ("error: missing fault at %p (%p+0)\n",
> + ptr + page_size - 1, ptr + page_size - 1);
> + TEST_COMPARE_STRING (proc.out.buffer, expected);
> + free (expected);
> + support_capture_subprocess_free (&proc);
> + xmunmap (ptr, 2 * page_size);
> + }
> +
> + return 0;
> +}
> +
> +#include <support/test-driver.c>
Ok.
> diff --git a/sysdeps/mach/hurd/support_disable_more_coredumps.c b/sysdeps/mach/hurd/support_disable_more_coredumps.c
> new file mode 100644
> index 0000000000..fe0fdcc89a
> --- /dev/null
> +++ b/sysdeps/mach/hurd/support_disable_more_coredumps.c
> @@ -0,0 +1,25 @@
> +/* Disable additional coredumps. Hurd version.
> + Copyright (C) 2019 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
> + <https://www.gnu.org/licenses/>. */
> +
> +#include <support/support.h>
> +
> +void
> +support_disable_more_coredumps (void)
> +{
> + /* Hurd does not have any additional coredumps to disable. */
> +}
>
I think current practice is just to enable the Linux specific call
within #ifdef __linux__, but I don't have a strong opinion.
@@ -148,7 +148,8 @@ endif
tests-static-normal := tst-leaks1-static tst-array1-static tst-array5-static \
tst-dl-iter-static \
tst-tlsalign-static tst-tlsalign-extern-static \
- tst-linkall-static tst-env-setuid tst-env-setuid-tunables
+ tst-linkall-static tst-env-setuid tst-env-setuid-tunables \
+ tst-relro-static tst-relro-static-dlopen
tests-static-internal := tst-tls1-static tst-tls2-static \
tst-ptrguard1-static tst-stackguard1-static \
tst-tls1-static-non-pie tst-libc_dlvsym-static
@@ -192,7 +193,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose \
tst-debug1 tst-main1 tst-absolute-sym tst-absolute-zero tst-big-note \
tst-unwind-ctor tst-unwind-main tst-audit13 \
- tst-sonamemove-link tst-sonamemove-dlopen tst-dlopen-aout
+ tst-sonamemove-link tst-sonamemove-dlopen tst-dlopen-aout \
+ tst-relro-shared
# reldep9
tests-internal += loadtest unload unload2 circleload1 \
neededtest neededtest2 neededtest3 neededtest4 \
@@ -308,8 +310,9 @@ test-xfail-tst-protected1b = yes
endif
ifeq (yesyes,$(have-fpie)$(build-shared))
modules-names += tst-piemod1
-tests += tst-pie1 tst-pie2 tst-dlopen-pie tst-dlopen-aout-pie
-tests-pie += tst-pie1 tst-pie2 tst-dlopen-aout-pie
+tests += tst-pie1 tst-pie2 tst-dlopen-pie tst-dlopen-aout-pie \
+ tst-relro-shared-pie
+tests-pie += tst-pie1 tst-pie2 tst-dlopen-aout-pie tst-relro-shared-pie
ifeq (yes,$(have-protected-data))
tests += vismain
tests-pie += vismain
@@ -1274,6 +1277,15 @@ CFLAGS-tst-dlopen-aout-pie.c += $(pie-ccflag)
$(objpfx)tst-dlopen-aout-pie: $(libdl) $(shared-thread-library)
$(objpfx)tst-dlopen-aout-container: $(libdl) $(shared-thread-library)
LDFLAGS-tst-dlopen-aout-container += -Wl,-rpath,\$$ORIGIN
+$(objpfx)tst-relro-shared: $(libdl)
+LDFLAGS-tst-relro-shared += $(relro-LDFLAGS)
+tst-relro-shared-no-pie = yes
+CFLAGS-tst-relro-shared-pie.c += $(pie-ccflag)
+$(objpfx)tst-relro-shared-pie: $(libdl)
+LDFLAGS-tst-relro-shared-pie += $(relro-LDFLAGS)
+tst-relro-static-dlopen-ENV = \
+ LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)dlfcn
+$(objpfx)tst-relro-static-dlopen: $(common-objpfx)dlfcn/libdl.a
CFLAGS-ifuncmain1pic.c += $(pic-ccflag)
CFLAGS-ifuncmain1picstatic.c += $(pic-ccflag)
new file mode 100644
@@ -0,0 +1,19 @@
+/* Test that RELRO is applied to the program, ld.so, libc.so. PIE version.
+ Copyright (C) 2019 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
+ <https://www.gnu.org/licenses/>. */
+
+#include "tst-relro-shared.c"
new file mode 100644
@@ -0,0 +1,50 @@
+/* Test that RELRO protection is applied to the program, ld.so, libc.so.
+ Copyright (C) 2019 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
+ <https://www.gnu.org/licenses/>. */
+
+#include <gnu/lib-names.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <support/check_fault.h>
+#include <support/xdlfcn.h>
+
+#include "tst-relro.h"
+
+static void (*const global_function_pointer) (void *) = free;
+
+static int
+do_test (void)
+{
+ printf ("info: checking global_function_pointer (%p)\n",
+ &global_function_pointer);
+ support_check_fault_write (&global_function_pointer,
+ sizeof (global_function_pointer));
+
+ check_relro_symbol (NULL, "_rtld_global_ro", LD_SO);
+ check_relro_symbol (NULL, "_nl_default_dirname", LIBC_SO);
+
+ /* Load libc.so into a new namespace and check that as well. */
+ void *new_libc = xdlmopen (LM_ID_NEWLM, LIBC_SO, RTLD_NOW);
+ check_relro_symbol (new_libc, "_rtld_global_ro", LD_SO);
+ check_relro_symbol (new_libc, "_nl_default_dirname", LIBC_SO);
+
+ xdlclose (new_libc);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
new file mode 100644
@@ -0,0 +1,45 @@
+/* Test RELRO protection in a statically linked program, with dlopen.
+ Copyright (C) 2019 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
+ <https://www.gnu.org/licenses/>. */
+
+#include <gnu/lib-names.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <support/check_fault.h>
+#include <support/xdlfcn.h>
+
+#include "tst-relro.h"
+
+static void (*const global_function_pointer) (void *) = free;
+
+static int
+do_test (void)
+{
+ printf ("info: checking global_function_pointer (%p)\n",
+ &global_function_pointer);
+ support_check_fault_write (&global_function_pointer,
+ sizeof (global_function_pointer));
+
+ void *libc = xdlopen (LIBC_SO, RTLD_NOW);
+ check_relro_symbol (libc, "_rtld_global_ro", LD_SO);
+ check_relro_symbol (libc, "_nl_default_dirname", LIBC_SO);
+ xdlclose (libc);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
new file mode 100644
@@ -0,0 +1,35 @@
+/* Test RELRO protection in a statically linked program.
+ Copyright (C) 2019 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
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <support/check_fault.h>
+
+static void (*const global_function_pointer) (void *) = free;
+
+static int
+do_test (void)
+{
+ printf ("info: checking global_function_pointer (%p)\n",
+ &global_function_pointer);
+ support_check_fault_write (&global_function_pointer,
+ sizeof (global_function_pointer));
+ return 0;
+}
+
+#include <support/test-driver.c>
new file mode 100644
@@ -0,0 +1,44 @@
+/* Support code for testing RELRO protection.
+ Copyright (C) 2019 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
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/xdlfcn.h>
+#include <support/check.h>
+#include <support/check_fault.h>
+#include <stdio.h>
+
+/* Check that the symbol NAME in HANDLE (which can be null) is not
+ located in writable memory. The corresponding address must be
+ located in the shared object with soname equal to EXPECTED_SONAME.
+
+ This function uses dlsym to avoid introducing copy relocations,
+ rather than accepting the pointer directly. Otherwise, the test
+ exercises RELRO protection in a different object. */
+static void
+check_relro_symbol (void *handle, const char *name,
+ const char *expected_soname)
+{
+ void *ptr = xdlsym (handle, name);
+ printf ("info: checking symbol %s in DSO %s at %p (handle %p)\n",
+ name, expected_soname, ptr, handle);
+ support_check_fault_write (ptr, 1);
+ Dl_info info;
+ void *actual_handle;
+ if (dladdr1 (ptr, &info, &actual_handle, RTLD_DL_HANDLE) == 0)
+ FAIL_EXIT1 ("dladdr1 for %s in %s failed", name, expected_soname);
+ TEST_COMPARE_STRING (dlinfo_soname (actual_handle), expected_soname);
+}
@@ -43,10 +43,12 @@ libsupport-routines = \
support_can_chroot \
support_capture_subprocess \
support_capture_subprocess_check \
+ support_check_fault_write \
support_chroot \
support_copy_file_range \
support_descriptor_supports_holes \
support_descriptors \
+ support_disable_more_coredumps \
support_enter_mount_namespace \
support_enter_network_namespace \
support_format_address_family \
@@ -218,6 +220,7 @@ tests = \
tst-support-namespace \
tst-support_blob_repeat \
tst-support_capture_subprocess \
+ tst-support_check_fault \
tst-support_descriptors \
tst-support_format_dns_packet \
tst-support_quote_blob \
new file mode 100644
@@ -0,0 +1,29 @@
+/* Check for faults at specific addresses.
+ Copyright (C) 2019 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
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef SUPPORT_CHECK_FAULT_H
+#define SUPPORT_CHECK_FAULT_H
+
+#include <stddef.h>
+
+/* Check that write access to SIZE individual bytes starting at
+ address results in SIGSEGV or SIGBUS signal. Both signals must not
+ be blocked and must have SIG_DFL disposition. */
+void support_check_fault_write (const void *address, size_t size);
+
+#endif /* SUPPORT_CHECK_FAULT_H */
@@ -80,6 +80,11 @@ char *support_quote_string (const char *);
regular file open for writing, and initially empty. */
int support_descriptor_supports_holes (int fd);
+/* For performance reasons, some tests need to disable all coredumps
+ (not just those which are written to the source directory, which
+ are disabled by the test driver). */
+void support_disable_more_coredumps (void);
+
/* Error-checking wrapper functions which terminate the process on
error. */
new file mode 100644
@@ -0,0 +1,72 @@
+/* Check for faults at specific addresses.
+ Copyright (C) 2019 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
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/check_fault.h>
+
+#include <signal.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <support/check.h>
+#include <support/support.h>
+#include <support/xunistd.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+/* Probe once at ADDRESS. Use START and INDEX in error reporting. */
+static bool
+check_one_address (volatile char *address, const void *start, size_t index)
+{
+ pid_t pid = xfork ();
+ if (pid == 0)
+ {
+ support_disable_more_coredumps ();
+ *address = 0xcc; /* Try to write an arbitrary value. */
+ _exit (0);
+ }
+ int status;
+ xwaitpid (pid, &status, 0);
+ if (WIFSIGNALED (status))
+ {
+ if (WTERMSIG (status) != SIGSEGV && WTERMSIG (status) != SIGBUS)
+ {
+ support_record_failure ();
+ printf ("error: unexpected signal %d at %p (%p+%zu)\n",
+ WTERMSIG (status), address, start, index);
+ return false;
+ }
+ }
+ else
+ {
+ support_record_failure ();
+ printf ("error: missing fault at %p (%p+%zu)\n",
+ address, start, index);
+ return false;
+ }
+ return true;
+}
+
+void
+support_check_fault_write (const void *address, size_t size)
+{
+ TEST_VERIFY (address != NULL);
+ TEST_VERIFY (size > 0);
+
+ for (size_t i = 0; i < size; ++i)
+ if (!check_one_address (((char *) address) + i, address, i))
+ break;
+}
new file mode 100644
@@ -0,0 +1,28 @@
+/* Disable additional coredumps. Version using <sys/prctl.h>.
+ Copyright (C) 2019 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
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/check.h>
+#include <support/support.h>
+#include <sys/prctl.h>
+
+void
+support_disable_more_coredumps (void)
+{
+ if (prctl (PR_SET_DUMPABLE, 0, 0, 0, 0) != 0)
+ FAIL_EXIT1 ("prctl (PR_SET_DUMPABLE) failure: %m");
+}
new file mode 100644
@@ -0,0 +1,118 @@
+/* Tests for support_fault_check_write.
+ Copyright (C) 2019 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
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/check_fault.h>
+
+#include <array_length.h>
+#include <stdlib.h>
+#include <support/capture_subprocess.h>
+#include <support/check.h>
+#include <support/support.h>
+#include <support/xunistd.h>
+#include <sys/mman.h>
+
+static void
+check_fault_two_bytes (void *address)
+{
+ support_check_fault_write (address, 2);
+}
+
+static int
+do_test (void)
+{
+ size_t page_size = xsysconf (_SC_PAGESIZE);
+
+ /* Tests with PROT_NONE, PROT_READ and PROT_EXEC are expected to
+ succeed. */
+ {
+ static const int prots[] = { PROT_NONE, PROT_READ, PROT_EXEC };
+ for (int i = 0; i < array_length (prots); ++i)
+ {
+ void *ptr = xmmap (NULL, 2, prots[i], MAP_PRIVATE | MAP_ANONYMOUS, -1);
+ support_check_fault_write (ptr, 2);
+ xmunmap (ptr, 2);
+ }
+ }
+
+ /* Do not call support_record_failure_reset below if the process has
+ already failed. */
+ int is_failed = support_record_failure_is_failed ();
+
+ /* Check that the lack of a fault for regular memory is reported at
+ the fist byte. */
+ {
+ void *ptr = xmalloc (2);
+ struct support_capture_subprocess proc
+ = support_capture_subprocess (check_fault_two_bytes, ptr);
+ support_capture_subprocess_check (&proc, "malloc", 0, sc_allow_stdout);
+ if (!is_failed)
+ support_record_failure_reset ();
+ char *expected = xasprintf ("error: missing fault at %p (%p+0)\n",
+ ptr, ptr);
+ TEST_COMPARE_STRING (proc.out.buffer, expected);
+ free (expected);
+ support_capture_subprocess_free (&proc);
+ free (ptr);
+ }
+
+ /* Check that a fault only at the first byte results in an error.
+ The probe range crosses a page boundary. */
+ is_failed = support_record_failure_is_failed ();
+ {
+ char *ptr = xmmap (NULL, 2 * page_size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1);
+ xmprotect (ptr, page_size, PROT_READ);
+ struct support_capture_subprocess proc
+ = support_capture_subprocess (check_fault_two_bytes,
+ ptr + page_size - 1);
+ support_capture_subprocess_check (&proc, "R, RW", 0, sc_allow_stdout);
+ if (!is_failed)
+ support_record_failure_reset ();
+ char *expected = xasprintf ("error: missing fault at %p (%p+1)\n",
+ ptr + page_size, ptr + page_size - 1);
+ TEST_COMPARE_STRING (proc.out.buffer, expected);
+ free (expected);
+ support_capture_subprocess_free (&proc);
+ xmunmap (ptr, 2 * page_size);
+ }
+
+ /* Check that a fault only at the second byte results in an error.
+ Again, the probe range crosses a page boundary. */
+ is_failed = support_record_failure_is_failed ();
+ {
+ char *ptr = xmmap (NULL, 2 * page_size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1);
+ xmprotect (ptr + page_size, page_size, PROT_READ);
+ struct support_capture_subprocess proc
+ = support_capture_subprocess (check_fault_two_bytes,
+ ptr + page_size - 1);
+ support_capture_subprocess_check (&proc, "RW, R", 0, sc_allow_stdout);
+ if (!is_failed)
+ support_record_failure_reset ();
+ char *expected = xasprintf ("error: missing fault at %p (%p+0)\n",
+ ptr + page_size - 1, ptr + page_size - 1);
+ TEST_COMPARE_STRING (proc.out.buffer, expected);
+ free (expected);
+ support_capture_subprocess_free (&proc);
+ xmunmap (ptr, 2 * page_size);
+ }
+
+ return 0;
+}
+
+#include <support/test-driver.c>
new file mode 100644
@@ -0,0 +1,25 @@
+/* Disable additional coredumps. Hurd version.
+ Copyright (C) 2019 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
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/support.h>
+
+void
+support_disable_more_coredumps (void)
+{
+ /* Hurd does not have any additional coredumps to disable. */
+}