From a93e2de99ef8926740cd512fb4e648668e9034f0 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Sun, 6 Aug 2017 00:23:20 +0000 Subject: [PATCH] tests: check handling of CLONE_PARENT'ed and CLONE_PTRACE'ed processes * tests/clone_parent.c: New file. * tests/clone_ptrace.c: Likewise. * tests/clone_parent.test: New test. * tests/clone_ptrace.test: Likewise. * tests/.gitignore: Add clone_parent and clone_ptrace. * tests/Makefile.am (check_PROGRAMS): Likewise. (MISC_TESTS): Add clone_parent.test and clone_ptrace.test. --- tests/.gitignore | 2 + tests/Makefile.am | 4 ++ tests/clone_parent.c | 80 +++++++++++++++++++++++++++++ tests/clone_parent.test | 3 ++ tests/clone_ptrace.c | 110 ++++++++++++++++++++++++++++++++++++++++ tests/clone_ptrace.test | 17 +++++++ 6 files changed, 216 insertions(+) create mode 100644 tests/clone_parent.c create mode 100755 tests/clone_parent.test create mode 100644 tests/clone_ptrace.c create mode 100755 tests/clone_ptrace.test diff --git a/tests/.gitignore b/tests/.gitignore index bdbf9642..e8f5ec60 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -31,6 +31,8 @@ chroot clock_adjtime clock_nanosleep clock_xettime +clone_parent +clone_ptrace copy_file_range count-f creat diff --git a/tests/Makefile.am b/tests/Makefile.am index fcc8d5d9..717e0370 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -86,6 +86,8 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ attach-p-cmd-p \ block_reset_raise_run \ caps-abbrev \ + clone_parent \ + clone_ptrace \ count-f \ execve-v \ execveat-v \ @@ -246,6 +248,8 @@ MISC_TESTS = \ attach-f-p.test \ attach-p-cmd.test \ bexecve.test \ + clone_parent.test \ + clone_ptrace.test \ count-f.test \ count.test \ detach-running.test \ diff --git a/tests/clone_parent.c b/tests/clone_parent.c new file mode 100644 index 00000000..2ec954eb --- /dev/null +++ b/tests/clone_parent.c @@ -0,0 +1,80 @@ +/* + * Check handling of CLONE_PARENT'ed processes. + * + * Copyright (c) 2017 The strace developers. + * 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 +#include +#include +#include +#include + +static int +child(void *const arg) +{ + return 42; +} + +#define child_stack_size (get_page_size() / 2) + +#ifdef IA64 +extern int __clone2(int (*)(void *), void *, size_t, int, void *, ...); +# define clone(fn, child_stack, flags, arg) \ + __clone2(fn, child_stack, child_stack_size, flags, arg) +#endif + +int +main(void) +{ + const pid_t pid = clone(child, tail_alloc(child_stack_size), + CLONE_PARENT | SIGCHLD, 0); + if (pid < 0) + perror_msg_and_fail("clone"); + + int status; + if (wait(&status) >= 0) + error_msg_and_fail("unexpected return code from wait"); + + while (!kill(pid, 0)) + ; + if (errno != ESRCH) + perror_msg_and_fail("kill"); + + FILE *const fp = fdopen(3, "a"); + if (!fp) + perror_msg_and_fail("fdopen"); + if (fprintf(fp, "%s: Exit of unknown pid %d ignored\n", + getenv("STRACE_EXE") ?: "strace", pid) < 0) + perror_msg_and_fail("fprintf"); + + puts("+++ exited with 0 +++"); + return 0; +} diff --git a/tests/clone_parent.test b/tests/clone_parent.test new file mode 100755 index 00000000..66b3bbbf --- /dev/null +++ b/tests/clone_parent.test @@ -0,0 +1,3 @@ +#!/bin/sh -efu +# Check handling of CLONE_PARENT'ed processes. +. "${srcdir=.}/clone_ptrace.test" diff --git a/tests/clone_ptrace.c b/tests/clone_ptrace.c new file mode 100644 index 00000000..48c099ae --- /dev/null +++ b/tests/clone_ptrace.c @@ -0,0 +1,110 @@ +/* + * Check handling of CLONE_PTRACE'ed processes. + * + * Copyright (c) 2015-2017 The strace developers. + * 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 +#include +#include +#include +#include +#include + +static siginfo_t sinfo; + +static void +handler(const int no, siginfo_t *const si, void *const uc) +{ + memcpy(&sinfo, si, sizeof(sinfo)); +} + +static int +child(void *const arg) +{ + for(;;) + pause(); + return 0; +} + +#define child_stack_size (get_page_size() / 2) + +#ifdef IA64 +extern int __clone2(int (*)(void *), void *, size_t, int, void *, ...); +# define clone(fn, child_stack, flags, arg) \ + __clone2(fn, child_stack, child_stack_size, flags, arg) +#endif + +int +main(void) +{ + const int sig = SIGUSR1; + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, sig); + if (sigprocmask(SIG_UNBLOCK, &mask, NULL)) + perror_msg_and_fail("sigprocmask"); + + const pid_t pid = clone(child, tail_alloc(child_stack_size), + CLONE_PTRACE | SIGCHLD, 0); + if (pid < 0) + perror_msg_and_fail("clone"); + + static const struct sigaction sa = { + .sa_sigaction = handler, + .sa_flags = SA_SIGINFO + }; + if (sigaction(SIGCHLD, &sa, NULL)) + perror_msg_and_fail("sigaction"); + + kill(pid, sig); + + FILE *const fp = fdopen(3, "a"); + if (!fp) + perror_msg_and_fail("fdopen"); + if (fprintf(fp, "%s: Detached unknown pid %d\n", + getenv("STRACE_EXE") ?: "strace", pid) < 0) + perror_msg_and_fail("fprintf"); + + int status; + while (wait(&status) != pid) { + if (errno != EINTR) + perror_msg_and_fail("wait"); + } + if (!WIFSIGNALED(status) || WTERMSIG(status) != sig) + error_msg_and_fail("unexpected child exit status %d", status); + + printf("--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_KILLED, si_pid=%d" + ", si_uid=%u, si_status=%s, si_utime=%u, si_stime=%u} ---\n" + "+++ exited with 0 +++\n", pid, geteuid(), "SIGUSR1", + (unsigned int) sinfo.si_utime, (unsigned int) sinfo.si_stime); + + return 0; +} diff --git a/tests/clone_ptrace.test b/tests/clone_ptrace.test new file mode 100755 index 00000000..a1f0237a --- /dev/null +++ b/tests/clone_ptrace.test @@ -0,0 +1,17 @@ +#!/bin/sh -efu +# Check handling of CLONE_PTRACE'ed processes. +. "${srcdir=.}/init.sh" + +run_prog > /dev/null 3>&1 +args="-e trace=none $args" +> "$LOG" || fail_ "failed to write $LOG" + +$STRACE -o "$LOG" $args > "$EXP" 2> "$OUT"-err 3> "$EXP"-err || { + msg="$STRACE $args failed with code $?" + cat "$OUT"-err "$LOG" >&2 + fail_ "$msg" +} + +cat "$OUT"-err >&2 +match_diff "$LOG" "$EXP" +match_diff "$OUT"-err "$EXP"-err -- 2.40.0