From 667b764c41bf0f683c8ea7c6d8cd6c1117794638 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Mon, 20 Feb 2017 00:10:35 +0000 Subject: [PATCH] tests: move get_sigset_size function to libtests * tests/get_sigset_size.c: New file. * tests/Makefile.am (libtests_a_SOURCES): Add it. * tests/tests.h (get_sigset_size): New prototype. * tests/ptrace.c: Do not check for __NR_rt_sigprocmask. (main): Use get_sigset_size. * tests/signalfd4.c: Do not check for __NR_rt_sigprocmask. (get_sigset_size): Remove. --- tests/Makefile.am | 1 + tests/get_sigset_size.c | 66 +++++++++++++++++++++++++++++++++++++++++ tests/ptrace.c | 47 ++++++++++------------------- tests/signalfd4.c | 24 ++------------- tests/tests.h | 3 ++ 5 files changed, 87 insertions(+), 54 deletions(-) create mode 100644 tests/get_sigset_size.c diff --git a/tests/Makefile.am b/tests/Makefile.am index 311d3bb3..cdc2ea2c 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -45,6 +45,7 @@ libtests_a_SOURCES = \ error_msg.c \ fill_memory.c \ get_page_size.c \ + get_sigset_size.c \ hexdump_strdup.c \ hexquote_strndup.c \ inode_of_sockfd.c \ diff --git a/tests/get_sigset_size.c b/tests/get_sigset_size.c new file mode 100644 index 00000000..357829da --- /dev/null +++ b/tests/get_sigset_size.c @@ -0,0 +1,66 @@ +/* + * Find out the size of kernel's sigset_t. + * + * Copyright (c) 2016-2017 Dmitry V. Levin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "tests.h" +#include +#include +#include + +/* + * If the sigset size specified to rt_sigprocmask is not equal to the size + * of kernel's sigset_t, the kernel does not look at anything else and fails + * with EINVAL. + * + * Otherwise, if both pointers specified to rt_sigprocmask are NULL, + * the kernel just returns 0. + * + * This vaguely documented kernel feature can be used to probe + * the kernel and find out the size of kernel's sigset_t. + */ + +unsigned int +get_sigset_size(void) +{ + static unsigned int set_size; + + if (!set_size) { + static const unsigned int big_size = 1024 / 8; + + for (set_size = big_size; set_size; set_size >>= 1) { + if (!syscall(__NR_rt_sigprocmask, SIG_SETMASK, + NULL, NULL, set_size)) + break; + } + + if (!set_size) + perror_msg_and_fail("rt_sigprocmask"); + } + + return set_size; +} diff --git a/tests/ptrace.c b/tests/ptrace.c index 80ce8cbb..67e746e6 100644 --- a/tests/ptrace.c +++ b/tests/ptrace.c @@ -30,16 +30,14 @@ #include "tests.h" #include -#ifdef __NR_rt_sigprocmask - -# include -# include -# include -# include -# include -# include -# include "ptrace.h" -# include +#include +#include +#include +#include +#include +#include +#include "ptrace.h" +#include static const char *errstr; @@ -178,15 +176,7 @@ main(void) const unsigned long pid = (unsigned long) 0xdefaced00000000ULL | (unsigned) getpid(); - unsigned int sigset_size; - - for (sigset_size = 1024 / 8; sigset_size; sigset_size >>= 1) { - if (!syscall(__NR_rt_sigprocmask, - SIG_SETMASK, NULL, NULL, sigset_size)) - break; - } - if (!sigset_size) - perror_msg_and_fail("rt_sigprocmask"); + const unsigned int sigset_size = get_sigset_size(); void *const k_set = tail_alloc(sigset_size); siginfo_t *const sip = tail_alloc(sizeof(*sip)); @@ -196,28 +186,28 @@ main(void) bad_request, (unsigned) pid, errstr); do_ptrace(PTRACE_PEEKDATA, pid, bad_request, bad_data); -# ifdef IA64 +#ifdef IA64 printf("ptrace(PTRACE_PEEKDATA, %u, %#lx) = %s\n", (unsigned) pid, bad_request, errstr); -# else +#else printf("ptrace(PTRACE_PEEKDATA, %u, %#lx, %#lx) = %s\n", (unsigned) pid, bad_request, bad_data, errstr); #endif do_ptrace(PTRACE_PEEKTEXT, pid, bad_request, bad_data); -# ifdef IA64 +#ifdef IA64 printf("ptrace(PTRACE_PEEKTEXT, %u, %#lx) = %s\n", (unsigned) pid, bad_request, errstr); -# else +#else printf("ptrace(PTRACE_PEEKTEXT, %u, %#lx, %#lx) = %s\n", (unsigned) pid, bad_request, bad_data, errstr); #endif do_ptrace(PTRACE_PEEKUSER, pid, bad_request, bad_data); -# ifdef IA64 +#ifdef IA64 printf("ptrace(PTRACE_PEEKUSER, %u, %#lx) = %s\n", (unsigned) pid, bad_request, errstr); -# else +#else printf("ptrace(PTRACE_PEEKUSER, %u, %#lx, %#lx) = %s\n", (unsigned) pid, bad_request, bad_data, errstr); #endif @@ -446,10 +436,3 @@ main(void) puts("+++ exited with 0 +++"); return 0; } - - -#else - -SKIP_MAIN_UNDEFINED("__NR_rt_sigprocmask") - -#endif diff --git a/tests/signalfd4.c b/tests/signalfd4.c index 47e49b50..772e1419 100644 --- a/tests/signalfd4.c +++ b/tests/signalfd4.c @@ -31,8 +31,7 @@ #include #include -#if defined __NR_rt_sigprocmask \ - && defined HAVE_SYS_SIGNALFD_H \ +#if defined HAVE_SYS_SIGNALFD_H \ && defined HAVE_SIGNALFD \ && defined O_CLOEXEC @@ -41,24 +40,6 @@ # include # include -static unsigned int -get_sigset_size(void) -{ - const unsigned int big_size = 1024 / 8; - unsigned int set_size; - - for (set_size = big_size; set_size; set_size >>= 1) { - if (!syscall(__NR_rt_sigprocmask, SIG_SETMASK, - NULL, NULL, set_size)) - break; - } - - if (!set_size) - perror_msg_and_fail("rt_sigprocmask"); - - return set_size; -} - int main(void) { @@ -80,7 +61,6 @@ main(void) #else -SKIP_MAIN_UNDEFINED("__NR_rt_sigprocmask && HAVE_SYS_SIGNALFD_H" - " && HAVE_SIGNALFD && O_CLOEXEC") +SKIP_MAIN_UNDEFINED("HAVE_SYS_SIGNALFD_H && HAVE_SIGNALFD && O_CLOEXEC") #endif diff --git a/tests/tests.h b/tests/tests.h index d4294de9..00050b5e 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -44,6 +44,9 @@ /* Cached sysconf(_SC_PAGESIZE). */ size_t get_page_size(void); +/* The size of kernel's sigset_t. */ +unsigned int get_sigset_size(void); + /* Print message and strerror(errno) to stderr, then exit(1). */ void perror_msg_and_fail(const char *, ...) ATTRIBUTE_FORMAT((printf, 1, 2)) ATTRIBUTE_NORETURN; -- 2.40.0