]> granicus.if.org Git - strace/commitdiff
tests: extend coverage of execve and execveat syscalls
authorDmitry V. Levin <ldv@altlinux.org>
Sun, 7 Feb 2016 14:37:53 +0000 (14:37 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Mon, 8 Feb 2016 18:25:33 +0000 (18:25 +0000)
Check decoding of inaccessible or partially inaccessible arrays.

* tests/execve-v.c: New file.
* tests/execveat-v.c: Likewise.
* tests/execve-v.test: New test.
* tests/execveat-v.test: Likewise.
* tests/execve.c: Rewrite.
* tests/execveat.c: Likewise.
* tests/execve.test: Likewise.
* tests/execveat.test: Likewise.
* tests/execve.expected: Remove.
* tests/execve-v.expected: Likewise.
* tests/execveat.expected: Likewise.
* tests/execveat-v.expected: Likewise.
* tests/.gitignore: Add execve-v and execveat-v.
* tests/Makefile.am (check_PROGRAMS): Likewise.
(TESTS): Add execve-v.test and execveat-v.test.
(EXTRA_DIST): Remove execve.expected, execve-v.expected,
execveat.expected, and execveat-v.expected.

14 files changed:
tests/.gitignore
tests/Makefile.am
tests/execve-v.c [new file with mode: 0644]
tests/execve-v.expected [deleted file]
tests/execve-v.test [new file with mode: 0755]
tests/execve.c
tests/execve.expected [deleted file]
tests/execve.test
tests/execveat-v.c [new file with mode: 0644]
tests/execveat-v.expected [deleted file]
tests/execveat-v.test [new file with mode: 0755]
tests/execveat.c
tests/execveat.expected [deleted file]
tests/execveat.test

index f6347c0bd5f15bca9517ca5caa545e4c1ff2ee45..690242e239df9551d1e86ea9a6e071e591891c69 100644 (file)
@@ -17,7 +17,9 @@ clock_xettime
 epoll_create1
 eventfd
 execve
+execve-v
 execveat
+execveat-v
 fanotify_mark
 fcntl
 fcntl64
index 935b13ab1bbf74caf6f816ea70fbcf0ebc444c12..a28a46aacd63bbea52537052f7a4401fdbb627b9 100644 (file)
@@ -67,7 +67,9 @@ check_PROGRAMS = \
        epoll_create1 \
        eventfd \
        execve \
+       execve-v \
        execveat \
+       execveat-v \
        fanotify_mark \
        fcntl \
        fcntl64 \
@@ -211,7 +213,9 @@ TESTS = \
        epoll_create1.test \
        eventfd.test \
        execve.test \
+       execve-v.test \
        execveat.test \
+       execveat-v.test \
        fanotify_mark.test \
        fcntl.test \
        fcntl64.test \
@@ -328,10 +332,6 @@ EXTRA_DIST = init.sh run.sh match.awk \
             caps.awk \
             dumpio.expected \
             eventfd.expected \
-            execve.expected \
-            execve-v.expected \
-            execveat.expected \
-            execveat-v.expected \
             fanotify_mark.expected \
             filter-unavailable.expected \
             fstatat.c \
diff --git a/tests/execve-v.c b/tests/execve-v.c
new file mode 100644 (file)
index 0000000..26bc9d6
--- /dev/null
@@ -0,0 +1,3 @@
+/* This file is part of execve-v strace test. */
+#define VERBOSE_EXECVE
+#include "execve.c"
diff --git a/tests/execve-v.expected b/tests/execve-v.expected
deleted file mode 100644 (file)
index 14fafb3..0000000
+++ /dev/null
@@ -1 +0,0 @@
-execve\("execve\\nfilename", \["execve\\nfilename", "first", "second"\], \["foobar=1", "foo\\nbar=2"\]\) += -1 ENOENT .*
diff --git a/tests/execve-v.test b/tests/execve-v.test
new file mode 100755 (executable)
index 0000000..599a80c
--- /dev/null
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# Check verbose decoding of execve syscall.
+
+. "${srcdir=.}/init.sh"
+
+check_prog grep
+run_prog > /dev/null
+
+OUT="$LOG.out"
+EXP="$LOG.exp"
+run_strace -veexecve $args > "$EXP"
+
+# Filter out execve() call made by strace.
+grep -F test.execve < "$LOG" > "$OUT"
+match_diff "$OUT" "$EXP"
+
+rm -f "$EXP" "$OUT"
index 09599780ad80ec6105c950f6ce192cf782a55415..9c0cfe0121a74ce827bf27c0d34cca65010feb61 100644 (file)
@@ -1,5 +1,7 @@
 /*
- * Copyright (c) 2015 Dmitry V. Levin <ldv@altlinux.org>
+ * This file is part of execve strace test.
+ *
+ * Copyright (c) 2015-2016 Dmitry V. Levin <ldv@altlinux.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include "tests.h"
+#include <errno.h>
+#include <stdio.h>
 #include <unistd.h>
 
-#define FILENAME "execve\nfilename"
-static const char * const argv[] =
-       { FILENAME, "first", "second", NULL, NULL, NULL };
-static const char * const envp[] =
-       { "foobar=1", "foo\nbar=2", NULL , "", NULL , "", NULL, NULL};
+#define FILENAME "test.execve\nfilename"
+#define Q_FILENAME "test.execve\\nfilename"
+
+static const char * const argv[] = {
+       FILENAME, "first", "second", (const char *) -1L,
+       (const char *) -2L, (const char *) -3L
+};
+static const char * const q_argv[] = {
+       Q_FILENAME, "first", "second"
+};
+
+static const char * const envp[] = {
+       "foobar=1", "foo\nbar=2", (const char *) -1L,
+       (const char *) -2L, (const char *) -3L
+};
+static const char * const q_envp[] = {
+       "foobar=1", "foo\\nbar=2"
+};
 
 int
 main(void)
 {
-       execve(FILENAME, (char * const *) argv, (char * const *) envp);
+       char ** const tail_argv = tail_memdup(argv, sizeof(argv));
+       char ** const tail_envp = tail_memdup(envp, sizeof(envp));
+
+       execve(FILENAME, tail_argv, tail_envp);
+       printf("execve(\"%s\""
+              ", [\"%s\", \"%s\", \"%s\", %p, %p, %p, ???]"
+#ifdef VERBOSE_EXECVE
+              ", [\"%s\", \"%s\", %p, %p, %p, ???]"
+#else
+              ", [/* 5 vars, unterminated */]"
+#endif
+              ") = -1 %s (%m)\n",
+              Q_FILENAME, q_argv[0], q_argv[1], q_argv[2],
+              argv[3], argv[4], argv[5],
+#ifdef VERBOSE_EXECVE
+              q_envp[0], q_envp[1], envp[2], envp[3], envp[4],
+#endif
+              errno == ENOSYS ? "ENOSYS" : "ENOENT");
+
+       tail_argv[ARRAY_SIZE(q_argv)] = NULL;
+       tail_envp[ARRAY_SIZE(q_envp)] = NULL;
+
+       execve(FILENAME, tail_argv, tail_envp);
+       printf("execve(\"%s\", [\"%s\", \"%s\", \"%s\"]"
+#ifdef VERBOSE_EXECVE
+              ", [\"%s\", \"%s\"]"
+#else
+              ", [/* 2 vars */]"
+#endif
+              ") = -1 %s (%m)\n",
+              Q_FILENAME, q_argv[0], q_argv[1], q_argv[2],
+#ifdef VERBOSE_EXECVE
+              q_envp[0], q_envp[1],
+#endif
+              errno == ENOSYS ? "ENOSYS" : "ENOENT");
+
+       execve(FILENAME, tail_argv + 2, tail_envp + 1);
+       printf("execve(\"%s\", [\"%s\"]"
+#ifdef VERBOSE_EXECVE
+              ", [\"%s\"]"
+#else
+              ", [/* 1 var */]"
+#endif
+              ") = -1 %s (%m)\n",
+              Q_FILENAME, q_argv[2],
+#ifdef VERBOSE_EXECVE
+              q_envp[1],
+#endif
+              errno == ENOSYS ? "ENOSYS" : "ENOENT");
+
+       char **const empty = tail_alloc(sizeof(*empty));
+       *empty = NULL;
+
+       execve(FILENAME, empty, empty);
+       printf("execve(\"%s\", []"
+#ifdef VERBOSE_EXECVE
+              ", []"
+#else
+              ", [/* 0 vars */]"
+#endif
+              ") = -1 %s (%m)\n",
+              Q_FILENAME, errno == ENOSYS ? "ENOSYS" : "ENOENT");
+
+       char str_a[] = "012345678901234567890123456789012";
+       char str_b[] = "_abcdefghijklmnopqrstuvwxyz()[]{}";
+#define DEFAULT_STRLEN ((unsigned int) sizeof(str_a) - 2)
+       char **const a = tail_alloc(sizeof(*a) * (DEFAULT_STRLEN + 2));
+       char **const b = tail_alloc(sizeof(*b) * (DEFAULT_STRLEN + 2));
+       unsigned int i;
+       for (i = 0; i <= DEFAULT_STRLEN; ++i) {
+               a[i] = &str_a[i];
+               b[i] = &str_b[i];
+       }
+       a[i] = b[i] = NULL;
+
+       execve(FILENAME, a, b);
+       printf("execve(\"%s\", [\"%.*s\"...", Q_FILENAME, DEFAULT_STRLEN, a[0]);
+       for (i = 1; i < DEFAULT_STRLEN; ++i)
+               printf(", \"%s\"", a[i]);
+#ifdef VERBOSE_EXECVE
+       printf(", \"%s\"", a[i]);
+#else
+       printf(", ...");
+#endif
+#ifdef VERBOSE_EXECVE
+       printf("], [\"%.*s\"...", DEFAULT_STRLEN, b[0]);
+       for (i = 1; i <= DEFAULT_STRLEN; ++i)
+               printf(", \"%s\"", b[i]);
+#else
+       printf("], [/* %u vars */", DEFAULT_STRLEN + 1);
+#endif
+       printf("]) = -1 %s (%m)\n", errno == ENOSYS ? "ENOSYS" : "ENOENT");
+
+       execve(FILENAME, a + 1, b + 1);
+       printf("execve(\"%s\", [\"%s\"", Q_FILENAME, a[1]);
+       for (i = 2; i <= DEFAULT_STRLEN; ++i)
+               printf(", \"%s\"", a[i]);
+#ifdef VERBOSE_EXECVE
+       printf("], [\"%s\"", b[1]);
+       for (i = 2; i <= DEFAULT_STRLEN; ++i)
+               printf(", \"%s\"", b[i]);
+#else
+       printf("], [/* %d vars */", DEFAULT_STRLEN);
+#endif
+       printf("]) = -1 %s (%m)\n", errno == ENOSYS ? "ENOSYS" : "ENOENT");
+
+       const void * const efault = tail_alloc(0);
+
+       execve(FILENAME, (char **) tail_argv[ARRAY_SIZE(q_argv)], efault);
+       printf("execve(\"%s\", NULL, %p"
+              ") = -1 %s (%m)\n",
+              Q_FILENAME, efault, errno == ENOSYS ? "ENOSYS" : "ENOENT");
+
+       execve(FILENAME, efault, NULL);
+       printf("execve(\"%s\", %p, NULL"
+              ") = -1 %s (%m)\n",
+              Q_FILENAME, efault, errno == ENOSYS ? "ENOSYS" : "ENOENT");
+
        return 0;
 }
diff --git a/tests/execve.expected b/tests/execve.expected
deleted file mode 100644 (file)
index e184d23..0000000
+++ /dev/null
@@ -1 +0,0 @@
-execve\("execve\\nfilename", \["execve\\nfilename", "first", "second"\], \[/\* 2 vars \*/\]\) += -1 ENOENT .*
index a1737cc9338ae69f73961ac56ea4450fc1e4f120..14cae625f44dd23ea588d906202343f2b06b7cf5 100755 (executable)
@@ -4,10 +4,15 @@
 
 . "${srcdir=.}/init.sh"
 
-run_prog
-run_strace $args
-match_grep
-run_strace -v $args
-match_grep "$LOG" "$srcdir/${ME_%.test}-v.expected"
+check_prog grep
+run_prog > /dev/null
 
-exit 0
+OUT="$LOG.out"
+EXP="$LOG.exp"
+run_strace -eexecve $args > "$EXP"
+
+# Filter out execve() call made by strace.
+grep -F test.execve < "$LOG" > "$OUT"
+match_diff "$OUT" "$EXP"
+
+rm -f "$EXP" "$OUT"
diff --git a/tests/execveat-v.c b/tests/execveat-v.c
new file mode 100644 (file)
index 0000000..530ddfc
--- /dev/null
@@ -0,0 +1,3 @@
+/* This file is part of execveat-v strace test. */
+#define VERBOSE_EXECVEAT
+#include "execveat.c"
diff --git a/tests/execveat-v.expected b/tests/execveat-v.expected
deleted file mode 100644 (file)
index ebac879..0000000
+++ /dev/null
@@ -1 +0,0 @@
-execveat\(AT_FDCWD, "execveat\\nfilename", \["execveat\\nfilename", "first", "second"\], \["foobar=1", "foo\\nbar=2"\], AT_SYMLINK_NOFOLLOW\|AT_EMPTY_PATH\) += -1 .*
diff --git a/tests/execveat-v.test b/tests/execveat-v.test
new file mode 100755 (executable)
index 0000000..776d290
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+# Check verbose decoding of execveat syscall.
+
+. "${srcdir=.}/init.sh"
+
+run_prog > /dev/null
+OUT="$LOG.out"
+run_strace -veexecveat $args > "$OUT"
+match_diff "$LOG" "$OUT"
+rm -f "$OUT"
index af3d08e7f2ec9e54cac6a77f7f849bf90fcbcabc..8ac2cd18a3910148a3cf9fde7aef2f19659a58d1 100644 (file)
@@ -1,4 +1,6 @@
 /*
+ * This file is part of execveat strace test.
+ *
  * Copyright (c) 2015-2016 Dmitry V. Levin <ldv@altlinux.org>
  * All rights reserved.
  *
  */
 
 #include "tests.h"
+#include <errno.h>
+#include <stdio.h>
 #include <unistd.h>
 #include <sys/syscall.h>
 
 #ifdef __NR_execveat
 
-#define FILENAME "execveat\nfilename"
-static const char * const argv[] =
-       { FILENAME, "first", "second", NULL, NULL, NULL };
-static const char * const envp[] =
-       { "foobar=1", "foo\nbar=2", NULL , "", NULL , "", NULL, NULL};
+# define FILENAME "test.execveat\nfilename"
+# define Q_FILENAME "test.execveat\\nfilename"
+
+static const char * const argv[] = {
+       FILENAME, "first", "second", (const char *) -1L,
+       (const char *) -2L, (const char *) -3L
+};
+static const char * const q_argv[] = {
+       Q_FILENAME, "first", "second"
+};
+
+static const char * const envp[] = {
+       "foobar=1", "foo\nbar=2", (const char *) -1L,
+       (const char *) -2L, (const char *) -3L
+};
+static const char * const q_envp[] = {
+       "foobar=1", "foo\\nbar=2"
+};
 
 int
 main(void)
 {
-       syscall(__NR_execveat, -100, FILENAME, argv, envp, 0x1100);
+       const char ** const tail_argv = tail_memdup(argv, sizeof(argv));
+       const char ** const tail_envp = tail_memdup(envp, sizeof(envp));
+
+       syscall(__NR_execveat, -100, FILENAME, tail_argv, tail_envp, 0x1100);
+       printf("execveat(AT_FDCWD, \"%s\""
+              ", [\"%s\", \"%s\", \"%s\", %p, %p, %p, ???]"
+#ifdef VERBOSE_EXECVEAT
+              ", [\"%s\", \"%s\", %p, %p, %p, ???]"
+#else
+              ", [/* 5 vars, unterminated */]"
+#endif
+              ", AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) = -1 %s (%m)\n",
+              Q_FILENAME, q_argv[0], q_argv[1], q_argv[2],
+              argv[3], argv[4], argv[5],
+#ifdef VERBOSE_EXECVEAT
+              q_envp[0], q_envp[1], envp[2], envp[3], envp[4],
+#endif
+              errno == ENOSYS ? "ENOSYS" : "ENOENT");
+
+       tail_argv[ARRAY_SIZE(q_argv)] = NULL;
+       tail_envp[ARRAY_SIZE(q_envp)] = NULL;
+
+       syscall(__NR_execveat, -100, FILENAME, tail_argv, tail_envp, 0x1100);
+       printf("execveat(AT_FDCWD, \"%s\", [\"%s\", \"%s\", \"%s\"]"
+#ifdef VERBOSE_EXECVEAT
+              ", [\"%s\", \"%s\"]"
+#else
+              ", [/* 2 vars */]"
+#endif
+              ", AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) = -1 %s (%m)\n",
+              Q_FILENAME, q_argv[0], q_argv[1], q_argv[2],
+#ifdef VERBOSE_EXECVEAT
+              q_envp[0], q_envp[1],
+#endif
+              errno == ENOSYS ? "ENOSYS" : "ENOENT");
+
+       syscall(__NR_execveat, -100, FILENAME, tail_argv + 2, tail_envp + 1, 0x1100);
+       printf("execveat(AT_FDCWD, \"%s\", [\"%s\"]"
+#ifdef VERBOSE_EXECVEAT
+              ", [\"%s\"]"
+#else
+              ", [/* 1 var */]"
+#endif
+              ", AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) = -1 %s (%m)\n",
+              Q_FILENAME, q_argv[2],
+#ifdef VERBOSE_EXECVEAT
+              q_envp[1],
+#endif
+              errno == ENOSYS ? "ENOSYS" : "ENOENT");
+
+       const char **const empty = tail_alloc(sizeof(*empty));
+       *empty = NULL;
+
+       syscall(__NR_execveat, -100, FILENAME, empty, empty, 0x1100);
+       printf("execveat(AT_FDCWD, \"%s\", []"
+#ifdef VERBOSE_EXECVEAT
+              ", []"
+#else
+              ", [/* 0 vars */]"
+#endif
+              ", AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) = -1 %s (%m)\n",
+              Q_FILENAME, errno == ENOSYS ? "ENOSYS" : "ENOENT");
+
+       char str_a[] = "012345678901234567890123456789012";
+       char str_b[] = "_abcdefghijklmnopqrstuvwxyz()[]{}";
+#define DEFAULT_STRLEN ((unsigned int) sizeof(str_a) - 2)
+       char **const a = tail_alloc(sizeof(*a) * (DEFAULT_STRLEN + 2));
+       char **const b = tail_alloc(sizeof(*b) * (DEFAULT_STRLEN + 2));
+       unsigned int i;
+       for (i = 0; i <= DEFAULT_STRLEN; ++i) {
+               a[i] = &str_a[i];
+               b[i] = &str_b[i];
+       }
+       a[i] = b[i] = NULL;
+
+       syscall(__NR_execveat, -100, FILENAME, a, b, 0x1100);
+       printf("execveat(AT_FDCWD, \"%s\", [\"%.*s\"...", Q_FILENAME, DEFAULT_STRLEN, a[0]);
+       for (i = 1; i < DEFAULT_STRLEN; ++i)
+               printf(", \"%s\"", a[i]);
+#ifdef VERBOSE_EXECVEAT
+       printf(", \"%s\"", a[i]);
+#else
+       printf(", ...");
+#endif
+#ifdef VERBOSE_EXECVEAT
+       printf("], [\"%.*s\"...", DEFAULT_STRLEN, b[0]);
+       for (i = 1; i <= DEFAULT_STRLEN; ++i)
+               printf(", \"%s\"", b[i]);
+#else
+       printf("], [/* %u vars */", DEFAULT_STRLEN + 1);
+#endif
+       printf("], AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) = -1 %s (%m)\n",
+              errno == ENOSYS ? "ENOSYS" : "ENOENT");
+
+       syscall(__NR_execveat, -100, FILENAME, a + 1, b + 1, 0x1100);
+       printf("execveat(AT_FDCWD, \"%s\", [\"%s\"", Q_FILENAME, a[1]);
+       for (i = 2; i <= DEFAULT_STRLEN; ++i)
+               printf(", \"%s\"", a[i]);
+#ifdef VERBOSE_EXECVEAT
+       printf("], [\"%s\"", b[1]);
+       for (i = 2; i <= DEFAULT_STRLEN; ++i)
+               printf(", \"%s\"", b[i]);
+#else
+       printf("], [/* %d vars */", DEFAULT_STRLEN);
+#endif
+       printf("], AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) = -1 %s (%m)\n",
+              errno == ENOSYS ? "ENOSYS" : "ENOENT");
+
+       const void * const efault = tail_alloc(0);
+
+       syscall(__NR_execveat, -100, FILENAME, NULL, efault, 0x1100);
+       printf("execveat(AT_FDCWD, \"%s\", NULL, %p"
+              ", AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) = -1 %s (%m)\n",
+              Q_FILENAME, efault, errno == ENOSYS ? "ENOSYS" : "ENOENT");
+
+       syscall(__NR_execveat, -100, FILENAME, efault, NULL, 0x1100);
+       printf("execveat(AT_FDCWD, \"%s\", %p, NULL"
+              ", AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) = -1 %s (%m)\n",
+              Q_FILENAME, efault, errno == ENOSYS ? "ENOSYS" : "ENOENT");
+
+       puts("+++ exited with 0 +++");
        return 0;
 }
 
diff --git a/tests/execveat.expected b/tests/execveat.expected
deleted file mode 100644 (file)
index 7383ed2..0000000
+++ /dev/null
@@ -1 +0,0 @@
-execveat\(AT_FDCWD, "execveat\\nfilename", \["execveat\\nfilename", "first", "second"\], \[/\* 2 vars \*/\], AT_SYMLINK_NOFOLLOW\|AT_EMPTY_PATH\) += -1 .*
index b371b0797511377b8d0266777c7c51c0c738d480..eb4a47aa4acbbb1a20dbdcb46fe578c827bac1fd 100755 (executable)
@@ -4,10 +4,8 @@
 
 . "${srcdir=.}/init.sh"
 
-run_prog
-run_strace $args
-match_grep
-run_strace -v $args
-match_grep "$LOG" "$srcdir/${ME_%.test}-v.expected"
-
-exit 0
+run_prog > /dev/null
+OUT="$LOG.out"
+run_strace -eexecveat $args > "$OUT"
+match_diff "$LOG" "$OUT"
+rm -f "$OUT"