From: Paul Chaignon Date: Mon, 1 Apr 2019 20:50:45 +0000 (+0200) Subject: tests: check status qualifier X-Git-Tag: v5.2~5 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1d9b0d3d8c186d8ea08020579a090e94a536d685;p=strace tests: check status qualifier This change adds 8 test cases for -e status with unfinished, failed, none, successful, detached, and the whole set. The test cases for failed, successful, and the whole set use chdir(2). Threaded test cases for unfinished and none rely on a child thread execve'ing the lead thread. There are additional single-threaded tests for status=none and status=unfinished. The test case for detached interrupts strace while attached to a sleeping process. * tests/status.c: New file. * tests/status-all.c: Likewise. * tests/status-failed.c: Likewise. * tests/status-detached.expected: Likewise. * tests/status-none.c: Likewise. * tests/status-none-threads.c: Likewise. * tests/status-successful.c: Likewise. * tests/status-unfinished-threads.c: Likewise. * tests/status-unfinished.c: Likewise. * tests/status-detached.test: New test. * tests/status-none-threads.test: Likewise. * tests/status-unfinished-threads.test: Likewise. * tests/tests.h (test_status_chdir): New prototype. * tests/.gitignore: Add status-all, status-failed, status-none, status-none-threads, status-successful, status-unfinished, and status-unfinished-threads. * tests/gen_tests.in: Add status-all, status-failed, status-successful, status-none, and status-unfinished. * tests/pure_executables.list: Likewise. * tests/Makefile.am (libtests_a_SOURCES): Add status.c. (check_PROGRAMS): Add status-none-threads and status-unfinished-threads. (status_none_threads_LDADD, status_unfinished_threads_LDADD): New variables. (MISC_TESTS): Add status-detached.test, status-none-threads.test, and status-unfinished-threads.test. (EXTRA_DIST): Add status-detached.expected. Co-Authored-by: Burkhard Kohl Signed-off-by: Paul Chaignon Co-Authored-by: Dmitry V. Levin --- diff --git a/tests/.gitignore b/tests/.gitignore index caf26676..7774ceec 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -579,6 +579,13 @@ stat stat64 statfs statfs64 +status-all +status-failed +status-none +status-none-threads +status-successful +status-unfinished +status-unfinished-threads statx swap sxetmask diff --git a/tests/Makefile.am b/tests/Makefile.am index fc914d54..ab2ae78d 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -49,6 +49,7 @@ libtests_a_SOURCES = \ signal2name.c \ skip_unavailable.c \ sprintrc.c \ + status.c \ tail_alloc.c \ test_netlink.h \ test_nlattr.h \ @@ -157,6 +158,8 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ sleep \ stack-fcall \ stack-fcall-mangled \ + status-none-threads \ + status-unfinished-threads \ threads-execve \ unblock_reset_raise \ unix-pair-send-recv \ @@ -191,6 +194,8 @@ preadv_pwritev_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64 pwritev_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64 stat64_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64 statfs_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64 +status_none_threads_LDADD = -lpthread $(LDADD) +status_unfinished_threads_LDADD = -lpthread $(LDADD) threads_execve_LDADD = -lpthread $(clock_LIBS) $(LDADD) times_LDADD = $(clock_LIBS) $(LDADD) truncate64_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64 @@ -338,6 +343,9 @@ MISC_TESTS = \ restart_syscall.test \ sigblock.test \ sigign.test \ + status-detached.test \ + status-none-threads.test \ + status-unfinished-threads.test \ strace-C.test \ strace-E.test \ strace-S.test \ @@ -425,6 +433,7 @@ EXTRA_DIST = \ sockaddr_xlat.c \ sockname.c \ stack-fcall.h \ + status-detached.expected \ strace-C.expected \ strace-E.expected \ strace-T.expected \ diff --git a/tests/gen_tests.in b/tests/gen_tests.in index d2d311ad..f90910f1 100644 --- a/tests/gen_tests.in +++ b/tests/gen_tests.in @@ -484,6 +484,11 @@ stat -a32 -v -P stat.sample -P /dev/full stat64 -a32 -v -P stat.sample -P /dev/full statfs -a17 statfs64 -a23 +status-all -a10 -e trace=chdir -e status=detached,failed,successful,unavailable,unfinished +status-failed -a10 -e trace=chdir -Z +status-none -e trace=all -e status=none +status-successful -a10 -e trace=chdir -z +status-unfinished -a10 -e trace=all -e status=unfinished statx -a32 -v -P stat.sample -P /dev/full swap -a23 -e trace=swapon,swapoff sxetmask -a11 -e trace=sgetmask,ssetmask diff --git a/tests/pure_executables.list b/tests/pure_executables.list index 96fad109..3224999e 100755 --- a/tests/pure_executables.list +++ b/tests/pure_executables.list @@ -491,6 +491,11 @@ stat stat64 statfs statfs64 +status-all +status-failed +status-none +status-successful +status-unfinished statx swap sxetmask diff --git a/tests/status-all.c b/tests/status-all.c new file mode 100644 index 00000000..db9510af --- /dev/null +++ b/tests/status-all.c @@ -0,0 +1,24 @@ +/* + * Check status=all filtering for failed and successful syscalls. + * + * Copyright (c) 2019 Intel Corporation + * Copyright (c) 2019 Paul Chaignon + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" +#include + +int +main(void) +{ + static const char sample_valid[] = "."; + static const char sample_invalid[] = ""; + + test_status_chdir(sample_valid, 1, 1); + test_status_chdir(sample_invalid, 1, 1); + puts("+++ exited with 0 +++"); + return 0; +} diff --git a/tests/status-detached.expected b/tests/status-detached.expected new file mode 100644 index 00000000..0a6325f5 --- /dev/null +++ b/tests/status-detached.expected @@ -0,0 +1 @@ +nanosleep\({tv_sec=2, tv_nsec=0}, diff --git a/tests/status-detached.test b/tests/status-detached.test new file mode 100755 index 00000000..febdc713 --- /dev/null +++ b/tests/status-detached.test @@ -0,0 +1,18 @@ +#!/bin/sh +# +# Check -e status=detached option. +# +# Copyright (c) 2019 Paul Chaignon +# All rights reserved. +# +# SPDX-License-Identifier: GPL-2.0-or-later + +. "${srcdir=.}/init.sh" + +# -I2 avoids blocking all fatal signals, the default when using -o. +$STRACE -o "$LOG" -I2 -e status=detached ../sleep 2 & +pid=$! +../sleep 1 +kill $pid +wait +match_grep diff --git a/tests/status-failed.c b/tests/status-failed.c new file mode 100644 index 00000000..81d2885a --- /dev/null +++ b/tests/status-failed.c @@ -0,0 +1,24 @@ +/* + * Check status=failed filtering for failed and successful syscalls. + * + * Copyright (c) 2019 Intel Corporation + * Copyright (c) 2019 Paul Chaignon + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" +#include + +int +main(void) +{ + static const char sample_valid[] = "."; + static const char sample_invalid[] = ""; + + test_status_chdir(sample_valid, 0, 1); + test_status_chdir(sample_invalid, 0, 1); + puts("+++ exited with 0 +++"); + return 0; +} diff --git a/tests/status-none-threads.c b/tests/status-none-threads.c new file mode 100644 index 00000000..8ba9857d --- /dev/null +++ b/tests/status-none-threads.c @@ -0,0 +1,53 @@ +/* + * Check status=none filtering when a non-leader thread invokes execve. + * + * Copyright (c) 2019 Paul Chaignon + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" +#include +#include +#include +#include +#include + +static pid_t leader; + +static void * +thread(void *arg) +{ + struct timespec ts = { .tv_nsec = 100000000 }; + (void) nanosleep(&ts, NULL); + + printf("%-5d +++ superseded by execve in pid %u +++\n", + leader, (int) syscall(__NR_gettid)); + + char *argv[] = {((char **) arg)[0], (char *) "0", NULL}; + execve(argv[0], argv, NULL); + perror_msg_and_fail("execve"); +} + +int +main(int ac, char **av) +{ + setvbuf(stdout, NULL, _IONBF, 0); + leader = getpid(); + + if (ac > 1) { + printf("%-5d +++ exited with 0 +++\n", leader); + return 0; + } + + pthread_t t; + errno = pthread_create(&t, NULL, thread, av); + if (errno) + perror_msg_and_fail("pthread_create"); + + struct timespec ts = { .tv_sec = 123 }; + (void) nanosleep(&ts, 0); + + return 1; +} diff --git a/tests/status-none-threads.test b/tests/status-none-threads.test new file mode 100755 index 00000000..cae8a79f --- /dev/null +++ b/tests/status-none-threads.test @@ -0,0 +1,44 @@ +#!/bin/sh +# +# Check status=none filtering when a non-leader thread invokes execve. +# +# Copyright (c) 2019 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: GPL-2.0-or-later + +. "${srcdir=.}/init.sh" + +# Check that PTRACE_EVENT_EXEC support in kernel is good enough. +# The kernel before commit v3.1-rc1~308^2~7 reported 0 instead of old pid. +require_min_kernel_version_or_skip 3.1 + +check_prog diff +run_prog_skip_if_failed date +%s > /dev/null +s0="$(date +%s)" + +run_prog > /dev/null + +set -- -a14 -f -e status=${status_filter:-none} $args + +# Due to probabilistic nature of the test, try it several times. +while :; do + > "$LOG" || fail_ "failed to write $LOG" + rc=0 + $STRACE -o "$LOG" "$@" > "$EXP" || { + rc=$? + cat < "$LOG" >&2 + } + + if [ "$rc" = 0 ] && diff -u -- "$EXP" "$LOG"; then + exit 0 + fi + + s1="$(date +%s)" + [ "$(($s1-$s0))" -gt "$(($TIMEOUT_DURATION/2))" ] || + continue + + [ "$rc" = 0 ] && + fail_ "$STRACE $* output mismatch" || + fail_ "$STRACE $* failed with code $rc" +done diff --git a/tests/status-none.c b/tests/status-none.c new file mode 100644 index 00000000..0144a60c --- /dev/null +++ b/tests/status-none.c @@ -0,0 +1,18 @@ +/* + * Check basic -e status=none syscall filtering. + * + * Copyright (c) 2019 The strace developers. + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" +#include + +int +main(void) +{ + puts("+++ exited with 0 +++"); + return 0; +} diff --git a/tests/status-successful.c b/tests/status-successful.c new file mode 100644 index 00000000..b37854af --- /dev/null +++ b/tests/status-successful.c @@ -0,0 +1,24 @@ +/* + * Check status=successful filtering for failed and successful syscalls. + * + * Copyright (c) 2019 Intel Corporation + * Copyright (c) 2019 Paul Chaignon + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" +#include + +int +main(void) +{ + static const char sample_valid[] = "."; + static const char sample_invalid[] = ""; + + test_status_chdir(sample_valid, 1, 0); + test_status_chdir(sample_invalid, 1, 0); + puts("+++ exited with 0 +++"); + return 0; +} diff --git a/tests/status-unfinished-threads.c b/tests/status-unfinished-threads.c new file mode 100644 index 00000000..098096c6 --- /dev/null +++ b/tests/status-unfinished-threads.c @@ -0,0 +1,55 @@ +/* + * Check status=unfinished filtering when a non-leader thread invokes execve. + * + * Copyright (c) 2019 Paul Chaignon + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" +#include +#include +#include +#include +#include + +static pid_t leader; + +static void * +thread(void *arg) +{ + struct timespec ts = { .tv_nsec = 100000000 }; + (void) nanosleep(&ts, NULL); + + printf("%-5d nanosleep({tv_sec=123, tv_nsec=0}, ) = ?\n" + "%-5d +++ superseded by execve in pid %u +++\n", + leader, leader, (int) syscall(__NR_gettid)); + + char *argv[] = {((char **) arg)[0], (char *) "0", NULL}; + execve(argv[0], argv, NULL); + perror_msg_and_fail("execve"); +} + +int +main(int ac, char **av) +{ + setvbuf(stdout, NULL, _IONBF, 0); + leader = getpid(); + + if (ac > 1) { + printf("%-5d exit_group(0) = ?\n" + "%-5d +++ exited with 0 +++\n", leader, leader); + return 0; + } + + pthread_t t; + errno = pthread_create(&t, NULL, thread, av); + if (errno) + perror_msg_and_fail("pthread_create"); + + struct timespec ts = { .tv_sec = 123 }; + (void) nanosleep(&ts, 0); + + return 1; +} diff --git a/tests/status-unfinished-threads.test b/tests/status-unfinished-threads.test new file mode 100755 index 00000000..f54a323f --- /dev/null +++ b/tests/status-unfinished-threads.test @@ -0,0 +1,12 @@ +#!/bin/sh +# +# Check status=unfinished filtering when a non-leader thread invokes execve. +# +# Copyright (c) 2019 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: GPL-2.0-or-later + +status_filter=unfinished + +. "${srcdir=.}"/status-none-threads.test diff --git a/tests/status-unfinished.c b/tests/status-unfinished.c new file mode 100644 index 00000000..de78eee4 --- /dev/null +++ b/tests/status-unfinished.c @@ -0,0 +1,19 @@ +/* + * Check basic -e status=unfinished syscall filtering. + * + * Copyright (c) 2019 Paul Chaignon + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" +#include + +int +main(void) +{ + puts("exit_group(0) = ?\n" + "+++ exited with 0 +++"); + return 0; +} diff --git a/tests/status.c b/tests/status.c new file mode 100644 index 00000000..82fd8b18 --- /dev/null +++ b/tests/status.c @@ -0,0 +1,21 @@ +/* + * Helper function to check -e status option. + * + * Copyright (c) 2019 Intel Corporation + * Copyright (c) 2019 Paul Chaignon + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" +#include +#include + +void +test_status_chdir(const char *dir, bool print_success, bool print_fail) +{ + long rc = chdir(dir); + if ((rc == -1 && print_fail) || (rc != -1 && print_success)) + printf("chdir(\"%s\") = %s\n", dir, sprintrc(rc)); +} diff --git a/tests/tests.h b/tests/tests.h index 1a1b02c3..4fca9886 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -208,6 +208,9 @@ int printxval(const struct xlat *, const unsigned long long, const char *); int socketcall(const int nr, const int call, long a1, long a2, long a3, long a4, long a5); +/* Call chdir and print strace output depending on flags. */ +void test_status_chdir(const char *dir, bool print_success, bool print_fail); + /* Wrappers for recvmmsg and sendmmsg syscalls. */ struct mmsghdr; struct timespec;