]> granicus.if.org Git - strace/commitdiff
tests: check decoding of clone flags
authorDmitry V. Levin <ldv@altlinux.org>
Thu, 20 Jun 2019 09:49:27 +0000 (09:49 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Thu, 20 Jun 2019 09:49:27 +0000 (09:49 +0000)
* 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.

tests/.gitignore
tests/Makefile.am
tests/clone-flags.c [new file with mode: 0644]
tests/clone-flags.test [new file with mode: 0755]
tests/pure_executables.list

index fb3fa928f8b244bbe668f20bdea11e4829c1caf5..9442021666d15a7638867981f9b12d654be4eec7 100644 (file)
@@ -41,6 +41,7 @@ chroot
 clock_adjtime
 clock_nanosleep
 clock_xettime
+clone-flags
 clone_parent
 clone_ptrace
 copy_file_range
index 9e99aff2f677da07c2fb8d2309d25fa0a3bb0927..7247a5977c3a03af6a4bbea914e8a82c5b215708 100644 (file)
@@ -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 (file)
index 0000000..dbcf71d
--- /dev/null
@@ -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 <errno.h>
+#include <sched.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+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 (executable)
index 0000000..cd71870
--- /dev/null
@@ -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
index 372252095ff63739c5d08f3a06a7dbc06c556c94..1e509dcfcf023c963809db9ced0b0cac4299fd72 100755 (executable)
@@ -31,6 +31,7 @@ chroot
 clock_adjtime
 clock_nanosleep
 clock_xettime
+clone-flags
 copy_file_range
 creat
 delete_module