__attribute__ ((__noreturn__)) attribute_hidden;
extern void __longjmp_chk (sigjmp_buf env, int val)
- __attribute__ ((noreturn)) attribute_hidden;
+ __attribute__ ((noreturn));
/* The redirection in the installed header does not work with
libc_hidden_proto. */
#define longjmp __longjmp_chk
#include <support/xsignal.h>
#include <support/xthread.h>
#include <support/xunistd.h>
+#include <support/check_mem_access.h>
#include <sys/mman.h>
#include <stdlib.h>
static long int pagesz;
-/* To check if the guard region is inaccessible, the thread tries read/writes
- on it and checks if a SIGSEGV is generated. */
-
-static volatile sig_atomic_t signal_jump_set;
-static sigjmp_buf signal_jmp_buf;
-
-static void
-sigsegv_handler (int sig)
-{
- if (signal_jump_set == 0)
- return;
-
- siglongjmp (signal_jmp_buf, sig);
-}
-
-static bool
-try_access_buf (char *ptr, bool write)
-{
- signal_jump_set = true;
-
- bool failed = sigsetjmp (signal_jmp_buf, 0) != 0;
- if (!failed)
- {
- if (write)
- *(volatile char *)(ptr) = 'x';
- else
- *(volatile char *)(ptr);
- }
-
- signal_jump_set = false;
- return !failed;
-}
-
static bool
try_read_buf (char *ptr)
{
- return try_access_buf (ptr, false);
+ return check_mem_access (ptr, false);
}
static bool
try_write_buf (char *ptr)
{
- return try_access_buf (ptr, true);
+ return check_mem_access (ptr, true);
}
static bool
{
pagesz = sysconf (_SC_PAGESIZE);
- {
- struct sigaction sa = {
- .sa_handler = sigsegv_handler,
- .sa_flags = SA_NODEFER,
- };
- sigemptyset (&sa.sa_mask);
- xsigaction (SIGSEGV, &sa, NULL);
- /* Some system generates SIGBUS accessing the guard area when it is
- setup with madvise. */
- xsigaction (SIGBUS, &sa, NULL);
- }
-
static const struct {
const char *descr;
void (*test)(void);
support_format_netent \
support_fuse \
support_isolate_in_subprocess \
+ support_mem_access \
support_mutex_pi_monotonic \
support_need_proc \
support_open_and_compare_file_bytes \
--- /dev/null
+/* Test verification functions for memory access checks.
+ Copyright (C) 2025 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_MEM_ACCESS_H
+#define SUPPORT_CHECK_MEM_ACCESS_H
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+/* To check if the a memory region is inaccessible, this function tries
+ read / write on the provided address ADDR and checks if a SIGSEGV is
+ generated. This function is not thread-safe and it changes signal
+ handlers for SIGSEGV and SIGBUS.
+ If WRITE is true, only the write operation is checked, otherwise only
+ the read operation is checked. */
+bool check_mem_access (const void *addr, bool write);
+
+__END_DECLS
+
+#endif // SUPPORT_CHECK_MEM_ACCESS_H
--- /dev/null
+/* Implementation of the test verification functions for memory access
+ checks.
+ Copyright (C) 2025 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 <setjmp.h>
+#include <signal.h>
+#include <support/xsignal.h>
+
+static sigjmp_buf sigsegv_jmp_buf;
+
+static void
+__sigsegv_handler (int signum)
+{
+ siglongjmp (sigsegv_jmp_buf, signum);
+}
+
+bool check_mem_access (const void *addr, bool write)
+{
+ /* This is obviously not thread-safe. */
+ static bool handler_set_up;
+ if (!handler_set_up)
+ {
+ struct sigaction sa = {
+ .sa_handler = __sigsegv_handler,
+ .sa_flags = SA_NODEFER,
+ };
+ sigemptyset (&sa.sa_mask);
+ xsigaction (SIGSEGV, &sa, NULL);
+ /* Some system generates SIGBUS accessing the guard area when it is
+ setup with madvise. */
+ xsigaction (SIGBUS, &sa, NULL);
+ handler_set_up = true;
+ }
+ int r = sigsetjmp (sigsegv_jmp_buf, 0);
+ if (r == 0)
+ {
+ if (write)
+ *(volatile char *)addr = 'x';
+ else
+ *(volatile char *)addr;
+ return true;
+ }
+ if (r == SIGSEGV || r == SIGBUS)
+ return false;
+ return true;
+}