tests: extend coverage of execve and execveat syscalls

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.
This commit is contained in:
Дмитрий Левин 2016-02-07 14:37:53 +00:00
parent 3c00e63b03
commit 23168c1e54
14 changed files with 342 additions and 34 deletions

2
tests/.gitignore vendored
View File

@ -17,7 +17,9 @@ clock_xettime
epoll_create1
eventfd
execve
execve-v
execveat
execveat-v
fanotify_mark
fcntl
fcntl64

View 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 \

3
tests/execve-v.c Normal file
View File

@ -0,0 +1,3 @@
/* This file is part of execve-v strace test. */
#define VERBOSE_EXECVE
#include "execve.c"

View File

@ -1 +0,0 @@
execve\("execve\\nfilename", \["execve\\nfilename", "first", "second"\], \["foobar=1", "foo\\nbar=2"\]\) += -1 ENOENT .*

18
tests/execve-v.test Executable file
View File

@ -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"

View 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
@ -25,17 +27,150 @@
* 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;
}

View File

@ -1 +0,0 @@
execve\("execve\\nfilename", \["execve\\nfilename", "first", "second"\], \[/\* 2 vars \*/\]\) += -1 ENOENT .*

View File

@ -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"

3
tests/execveat-v.c Normal file
View File

@ -0,0 +1,3 @@
/* This file is part of execveat-v strace test. */
#define VERBOSE_EXECVEAT
#include "execveat.c"

View File

@ -1 +0,0 @@
execveat\(AT_FDCWD, "execveat\\nfilename", \["execveat\\nfilename", "first", "second"\], \["foobar=1", "foo\\nbar=2"\], AT_SYMLINK_NOFOLLOW\|AT_EMPTY_PATH\) += -1 .*

11
tests/execveat-v.test Executable file
View File

@ -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"

View 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.
*
@ -26,21 +28,156 @@
*/
#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;
}

View File

@ -1 +0,0 @@
execveat\(AT_FDCWD, "execveat\\nfilename", \["execveat\\nfilename", "first", "second"\], \[/\* 2 vars \*/\], AT_SYMLINK_NOFOLLOW\|AT_EMPTY_PATH\) += -1 .*

View File

@ -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"