]> granicus.if.org Git - strace/commitdiff
tests: add multi-process check to qual_fault.test
authorEugene Syromyatnikov <evgsyr@gmail.com>
Mon, 3 Jul 2017 19:29:28 +0000 (21:29 +0200)
committerDmitry V. Levin <ldv@altlinux.org>
Mon, 3 Jul 2017 19:31:04 +0000 (19:31 +0000)
Check that syscall counters used for tampering are per-tcb.

* tests/qual_fault.c: Include <fcntl.h> for open(),
<sys/param.h> for PATH_MAX, and <sys/wait.h> for wait().
(expfd): Rename to exp_fd, remove const qualifier and initialization.
(gotfd): Rename to got_fd, remove const qualifier and initialization.
(out_fd): New variable, for the expected strace output.
(open_file): New helper function.
(main): Remove st, add num_procs, proc, exp_prefix, got_prefix,
out_prefix, pid_prefix.  Remove stat asserts, update argc assert.
Add num_procs, exp_prefix, got_prefix, out_prefix, pid_prefix
initialization.  Add per-process loop, open expfd, gotfd, out_fd, pidfd
in each one, print process's pid to pidfd, print exit message to out_fd.
Add wait() call for each forked process.
* tests/qual_fault.test (N): increase to 100 in order to check
concurrent process execution.
(check_fault_injection): Take additional argument for the process
count, pass it to qual_fault, add filename variables for expected strace
output and pid file, pass them to qual_fault.
Specify -ff parameter to strace invocation.
Compare write and strace output for the each process.
Update all check_fault_injection invocation with process count argument,
add an invocation with 4 concurrent processes.
* tests/init.sh (TIMEOUT_DURATION): Raise from 120 to 300.

Co-authored-by: Dmitry V. Levin <ldv@altlinux.org>
tests/init.sh
tests/qual_fault.c
tests/qual_fault.test

index 013a33d920496b69b02c5f4a2058b8ae5f49dd81..2d4d0b41c3cf27a4d630e93eced545dd08f61864 100644 (file)
@@ -366,7 +366,7 @@ else
                STRACE=../strace
 fi
 
-: "${TIMEOUT_DURATION:=120}"
+: "${TIMEOUT_DURATION:=300}"
 : "${SLEEP_A_BIT:=sleep 1}"
 
 [ -z "${VERBOSE-}" ] ||
index ab692cb872247edfe9e1204c53a67ced9c757663..05401dec344a178acb334053c0d16e74334cc178 100644 (file)
 
 #include <assert.h>
 #include <errno.h>
+#include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <sys/param.h>
 #include <sys/stat.h>
 #include <sys/uio.h>
+#include <sys/wait.h>
 
-static const int expfd = 4;
-static const int gotfd = 5;
+static int exp_fd;
+static int got_fd;
+static int out_fd;
 
 #define DEFAULT_ERRNO ENOSYS
 
@@ -58,13 +62,13 @@ invoke(int fail)
        int rc;
 
        if (!fail) {
-               rc = write(expfd, io.iov_base, io.iov_len);
+               rc = write(exp_fd, io.iov_base, io.iov_len);
                if (rc != (int) io.iov_len)
                        perror_msg_and_fail("write");
        }
 
        errno = 0;
-       rc = writev(gotfd, &io, 1);
+       rc = writev(got_fd, &io, 1);
 
        if (fail) {
                if (!(rc == -1 && errno == err))
@@ -74,11 +78,11 @@ invoke(int fail)
 
                if (is_raw)
                        tprintf("writev(%#x, %p, 0x1) = -1 (errno %d)"
-                               " (INJECTED)\n", gotfd, &io, err);
+                               " (INJECTED)\n", got_fd, &io, err);
                else
                        tprintf("writev(%d, [{iov_base=\"%s\", iov_len=%d}], 1)"
                                " = -1 %s (%m) (INJECTED)\n",
-                               gotfd, buf, (int) io.iov_len, errstr);
+                               got_fd, buf, (int) io.iov_len, errstr);
        } else {
                if (rc != (int) io.iov_len)
                        perror_msg_and_fail("expected %d"
@@ -86,23 +90,35 @@ invoke(int fail)
                                            (int) io.iov_len, rc, errno);
 
                if (is_raw)
-                       tprintf("writev(%#x, %p, 0x1) = %#x\n", gotfd, &io, rc);
+                       tprintf("writev(%#x, %p, 0x1) = %#x\n",
+                               got_fd, &io, rc);
                else
                        tprintf("writev(%d, [{iov_base=\"%s\", iov_len=%d}], 1)"
                                " = %d\n",
-                               gotfd, buf, (int) io.iov_len, (int) io.iov_len);
+                               got_fd, buf, (int) io.iov_len,
+                               (int) io.iov_len);
        }
 }
 
-int
-main(int argc, char *argv[])
+static int
+open_file(const char *prefix, int proc)
 {
-       struct stat st;
+       static const int open_flags = O_WRONLY | O_TRUNC | O_CREAT;
+       static char path[PATH_MAX + 1];
+
+       snprintf(path, sizeof(path), "%s.%d", prefix, proc);
 
-       assert(fstat(expfd, &st) == 0);
-       assert(fstat(gotfd, &st) == 0);
+       int fd = open(path, open_flags, 0600);
+       if (fd < 0)
+               perror_msg_and_fail("open: %s", path);
+
+       return fd;
+}
 
-       assert(argc == 6);
+int
+main(int argc, char *argv[])
+{
+       assert(argc == 11);
 
        is_raw = !strcmp("raw", argv[1]);
 
@@ -125,25 +141,71 @@ main(int argc, char *argv[])
        first = atoi(argv[3]);
        step = atoi(argv[4]);
        iter = atoi(argv[5]);
+       int num_procs = atoi(argv[6]);
+       char *exp_prefix = argv[7];
+       char *got_prefix = argv[8];
+       char *out_prefix = argv[9];
+       char *pid_prefix = argv[10];
 
        assert(first > 0);
        assert(step >= 0);
+       assert(num_procs > 0);
+
+       int proc;
+       for (proc = 0; proc < num_procs; ++proc) {
+               int ret = fork();
+
+               if (ret < 0)
+                       perror_msg_and_fail("fork");
 
-       tprintf("%s", "");
+               if (ret > 0) {
+                       int pidfd = open_file(pid_prefix, proc);
 
-       int i;
-       for (i = 1; i <= iter; ++i) {
-               int fail = 0;
-               if (first > 0) {
-                       --first;
-                       if (first == 0) {
-                               fail = 1;
-                               first = step;
+                       char pidstr[sizeof(ret) * 3];
+                       int len = snprintf(pidstr, sizeof(pidstr), "%d", ret);
+                       assert(len > 0 && len < (int) sizeof(pidstr));
+                       assert(write(pidfd, pidstr, len) == len);
+
+                       close(pidfd);
+
+                       continue;
+               }
+
+               tprintf("%s", "");
+
+               exp_fd = open_file(exp_prefix, proc);
+               got_fd = open_file(got_prefix, proc);
+               out_fd = open_file(out_prefix, proc);
+
+               /* This magic forces tprintf to write where we want it. */
+               dup2(out_fd, 3);
+
+               int i;
+               for (i = 1; i <= iter; ++i) {
+                       int fail = 0;
+                       if (first > 0) {
+                               --first;
+                               if (first == 0) {
+                                       fail = 1;
+                                       first = step;
+                               }
                        }
+                       invoke(fail);
                }
-               invoke(fail);
+
+               tprintf("%s\n", "+++ exited with 0 +++");
+               return 0;
+       }
+
+       for (proc = 0; proc < num_procs; ++proc) {
+               int status;
+               int ret = wait(&status);
+               if (ret <= 0)
+                       perror_msg_and_fail("wait %d", proc);
+               if (status)
+                       error_msg_and_fail("wait: pid=%d status=%d",
+                                          ret, status);
        }
 
-       tprintf("%s\n", "+++ exited with 0 +++");
        return 0;
 }
index f8e57d2bd593dc0a5fdc398f43f4e435b744334b..12b0a850983ee128e755f1bec025aaa2d4a6073c 100755 (executable)
 # F+
 # F+S
 
-N=16
+N=100
 
 check_fault_injection()
 {
-       local trace fault err first step extra
+       local trace fault err first step procs extra
        trace=$1; shift
        fault=$1; shift
        err=$1; shift
        first=$1; shift
        step=$1; shift
+       procs=$1; shift
        extra="$*"
 
        local when=
@@ -74,30 +75,39 @@ check_fault_injection()
 
        outexp="$NAME.out.exp"
        outgot="$NAME.out.got"
+       outout="$NAME.out.out"
+       outpid="$NAME.pid"
 
-       run_strace -a11 -e trace=$trace \
+       run_strace -a11 -ff -e trace=$trace \
                "$@" -e fault=$fault$when$error $extra \
                ../$NAME $raw "$err" "$first" "$step" $N \
-               > "$EXP" 4> "$outexp" 5> "$outgot"
+               "$procs" "$outexp" "$outgot" "$outout" "$outpid"
 
-       match_diff "$EXP" "$LOG"
-       match_diff "$outexp" "$outgot"
+       for i in $(seq 0 $((procs - 1)) )
+       do
+               pid=$(cat "$outpid.$i")
+
+               match_diff "$outout.$i" "$LOG.$pid"
+               match_diff "$outexp.$i" "$outgot.$i"
+       done
 }
 
 for err in '' ENOSYS 22 einval; do
        for fault in writev desc,51; do
                check_fault_injection \
-                       writev $fault "$err" '' '' -efault=chdir
+                       writev $fault "$err" '' '' -efault=chdir
                check_fault_injection \
-                       writev $fault "$err" '' '' -efault=chdir -efault=none
+                       writev $fault "$err" '' '' -efault=chdir -efault=none
                for F in 1 2 3 5 7 11; do
                        check_fault_injection \
-                               writev $fault "$err" $F ''
+                               writev $fault "$err" $F '' 1
                        check_fault_injection \
-                               writev $fault "$err" $F +
+                               writev $fault "$err" $F + 1
                        for S in 1 2 3 5 7 11; do
                                check_fault_injection \
-                                       writev $fault "$err" $F $S
+                                       writev $fault "$err" $F $S 1
+                               check_fault_injection \
+                                       writev $fault "$err" $F $S 4
                        done
                done
        done