From: Dmitry V. Levin Date: Thu, 20 Jun 2019 09:49:27 +0000 (+0000) Subject: tests: check decoding of clone flags X-Git-Tag: v5.2~57 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b981cf427f6ac6ef61bb011dfac56bae8c28a783;p=strace tests: check decoding of clone flags * tests/clone-flags.c: New file. * tests/pure_executables.list: Add clone-flags. * tests/.gitignore: Likewise. * tests/clone-flags.test: New test. * tests/Makefile.am (DECODER_TESTS): Add clone-flags.test. --- diff --git a/tests/.gitignore b/tests/.gitignore index fb3fa928..94420216 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -41,6 +41,7 @@ chroot clock_adjtime clock_nanosleep clock_xettime +clone-flags clone_parent clone_ptrace copy_file_range diff --git a/tests/Makefile.am b/tests/Makefile.am index 9e99aff2..7247a597 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -226,6 +226,7 @@ DECODER_TESTS = \ btrfs-wX.test \ caps-abbrev.test \ caps.test \ + clone-flags.test \ eventfd.test \ execve-v.test \ execve.test \ diff --git a/tests/clone-flags.c b/tests/clone-flags.c new file mode 100644 index 00000000..dbcf71df --- /dev/null +++ b/tests/clone-flags.c @@ -0,0 +1,115 @@ +/* + * Check decoding of clone flags. + * + * Copyright (c) 2017-2019 The strace developers. + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" + +#include +#include +#include +#include +#include +#include +#include + +static const int child_exit_status = 42; +static pid_t pid; + +static pid_t +wait_cloned(pid_t pid, int sig, const char *text) +{ + if (pid < 0) + perror_msg_and_fail("clone %s", text); + int status; + pid_t rc = wait(&status); + if (sig) { + if (rc != pid) + perror_msg_and_fail("unexpected wait rc %d from %s", + rc, text); + if (!WIFEXITED(status) || + WEXITSTATUS(status) != child_exit_status) + error_msg_and_fail("unexpected wait status %#x from %s", + status, text); + } else { + if (rc >= 0) + error_msg_and_fail("unexpected wait rc %d from %s", + rc, text); + } + return pid; +} + +#ifdef IA64 +extern int __clone2(int (*)(void *), void *, size_t, int, void *, ...); +#define do_clone(fn_, stack_, size_, flags_, arg_, ...) \ + wait_cloned(__clone2((fn_), (stack_), (size_), (flags_), (arg_), \ + ## __VA_ARGS__), (flags_) & 0xff, #flags_) +# define SYSCALL_NAME "clone2" +# define STACK_SIZE_FMT ", stack_size=%#lx" +# define STACK_SIZE_ARG child_stack_size, +#else +#define do_clone(fn_, stack_, size_, flags_, arg_, ...) \ + wait_cloned(clone((fn_), (stack_), (flags_), (arg_), \ + ## __VA_ARGS__), (flags_) & 0xff, #flags_) +# define SYSCALL_NAME "clone" +# define STACK_SIZE_FMT "" +# define STACK_SIZE_ARG +#endif + +static int +child(void *const arg) +{ + return child_exit_status; +} + +int +main(void) +{ + const unsigned long child_stack_size = get_page_size(); + void *const child_stack = + tail_alloc(child_stack_size * 2) + child_stack_size; + + const char *child_stack_expected_str = getenv("CHILD_STACK_EXPECTED"); + const char *child_stack_reported_str = getenv("CHILD_STACK_REPORTED"); + + if (!child_stack_expected_str || !child_stack_reported_str) { + const unsigned long child_stack_base = + (unsigned long) child_stack / 0x1000; + pid = do_clone(child, child_stack, child_stack_size, + SIGCHLD, 0); + printf("%s\\(child_stack=(%#lx|%#lx)[[:xdigit:]]{3}" + STACK_SIZE_FMT ", flags=%s\\) = %d\n", + SYSCALL_NAME, child_stack_base, child_stack_base - 1, + STACK_SIZE_ARG "SIGCHLD", pid); + return 0; + } + const unsigned long child_stack_expected = + strtoul(child_stack_expected_str, 0, 16); + const unsigned long child_stack_reported = + strtoul(child_stack_reported_str, 0, 16); + const unsigned long child_stack_printed = + (unsigned long) child_stack + + (child_stack_reported - child_stack_expected); + + pid = do_clone(child, child_stack, child_stack_size, CLONE_FS, 0); + printf("%s(child_stack=%#lx" STACK_SIZE_FMT ", flags=%s) = %d\n", + SYSCALL_NAME, child_stack_printed, STACK_SIZE_ARG + "CLONE_FS", pid); + + pid = do_clone(child, child_stack, child_stack_size, SIGCHLD, 0); + printf("%s(child_stack=%#lx" STACK_SIZE_FMT ", flags=%s) = %d\n", + SYSCALL_NAME, child_stack_printed, STACK_SIZE_ARG + "SIGCHLD", pid); + + pid = do_clone(child, child_stack, child_stack_size, + CLONE_FS|SIGCHLD, 0); + printf("%s(child_stack=%#lx" STACK_SIZE_FMT ", flags=%s) = %d\n", + SYSCALL_NAME, child_stack_printed, STACK_SIZE_ARG + "CLONE_FS|SIGCHLD", pid); + + return 0; +} diff --git a/tests/clone-flags.test b/tests/clone-flags.test new file mode 100755 index 00000000..cd718709 --- /dev/null +++ b/tests/clone-flags.test @@ -0,0 +1,24 @@ +#!/bin/sh -efu +# +# Check decoding of clone flags. +# +# Copyright (c) 2019 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: GPL-2.0-or-later + +. "${srcdir=.}/init.sh" + +case "$STRACE_ARCH" in + ia64) syscall=clone2 ;; + *) syscall=clone ;; +esac + +# Find out the expected and reported child stack addresses. +run_strace_match_grep -qq -e signal=none -e trace=$syscall +CHILD_STACK_EXPECTED="$(sed -n 's/^clone[^(]*(child_stack=(\(0x[[:xdigit:]]\+\)|.*/\1/p' "$EXP")000" +CHILD_STACK_REPORTED="$(sed -n 's/^clone[^(]*(child_stack=\(0x[[:xdigit:]]\+\),.*/\1/p' "$LOG")" +export CHILD_STACK_EXPECTED CHILD_STACK_REPORTED + +# Use child stack addresses to check decoding. +run_strace_match_diff -a35 -qq -y -e signal=none -e trace=$syscall diff --git a/tests/pure_executables.list b/tests/pure_executables.list index 37225209..1e509dcf 100755 --- a/tests/pure_executables.list +++ b/tests/pure_executables.list @@ -31,6 +31,7 @@ chroot clock_adjtime clock_nanosleep clock_xettime +clone-flags copy_file_range creat delete_module