Fix meaning of negated sets in fault expressions

Change the parser of fault expression to follow the POLA:
-e fault=!SET
means that all syscalls except those from SET are subject to fault
injection;
-e fault=!SET1:error=ERRNO1, -e fault=!SET2:error=ERRNO2
means that all syscalls except those from SET2 are subject to fault
injection with error code ERRNO2, and all syscalls from SET2 that are
not in SET1 are subject to fault injection with error code ERRNO1.

* syscall.c (qualify_scno, qualify_syscall_class, qualify_syscall_name):
Handle negated QUAL_FAULT case differently.
* tests/fault_syntax.test: Add checks of negated sets.
This commit is contained in:
Дмитрий Левин 2016-11-29 02:11:48 +00:00
parent c84536f975
commit 4399fa976a
2 changed files with 40 additions and 14 deletions

View File

@ -457,11 +457,27 @@ static bool
qualify_scno(const char *const s, const unsigned int bitflag,
const int not, const struct fault_opts *const fopts)
{
int i = string_to_uint_upto(s, MAX_NSYSCALLS - 1);
if (i < 0)
int n = string_to_uint_upto(s, MAX_NSYSCALLS - 1);
if (n < 0)
return false;
qualify_one(i, bitflag, not, -1, fopts);
if (not && fopts) {
/* set bitflag for all syscall numbers except n */
unsigned int p;
for (p = 0; p < SUPPORTED_PERSONALITIES; ++p) {
unsigned int i;
for (i = 0; i < nsyscall_vec[p]; ++i) {
if (i != (unsigned int) n
&& sysent_vec[p][i].sys_name) {
qualify_one(i, bitflag, 0, p, fopts);
}
}
}
} else {
qualify_one(n, bitflag, not, -1, fopts);
}
return true;
}
@ -501,9 +517,11 @@ qualify_syscall_class(const char *const s, const unsigned int bitflag,
unsigned int i;
for (i = 0; i < nsyscall_vec[p]; ++i) {
if (sysent_vec[p][i].sys_name
&& (sysent_vec[p][i].sys_flags & n) == n) {
qualify_one(i, bitflag, not, p, fopts);
if (!sysent_vec[p][i].sys_name)
continue;
const bool match = (sysent_vec[p][i].sys_flags & n) == n;
if (match ^ (not && fopts)) {
qualify_one(i, bitflag, not && !fopts, p, fopts);
}
}
}
@ -522,10 +540,12 @@ qualify_syscall_name(const char *const s, const unsigned int bitflag,
unsigned int i;
for (i = 0; i < nsyscall_vec[p]; ++i) {
if (sysent_vec[p][i].sys_name
&& strcmp(s, sysent_vec[p][i].sys_name) == 0) {
qualify_one(i, bitflag, not, p, fopts);
found = true;
if (!sysent_vec[p][i].sys_name)
continue;
const bool match = !strcmp(s, sysent_vec[p][i].sys_name);
found = found || match;
if (match ^ (not && fopts)) {
qualify_one(i, bitflag, not && !fopts, p, fopts);
}
}
}

View File

@ -40,16 +40,16 @@ fail_with()
"strace -e fault=$* failed to handle an argument error properly"
}
for arg in '' , ,, ,,, : :: ::: \
for arg in '' , ,, ,,, : :: ::: \! \!, \!: \
invalid_syscall_name \
invalid_syscall_name:when=3 \
-1 \
-1 \!-1 \
-1:when=4 \
-2 \
-2:when=5 \
32767 \
32767 \!32767 \
32767:when=6 \
chdir:42 \
chdir:42 \!chdir:42 \
chdir:42:when=7 \
chdir:invalid \
chdir:invalid:when=8 \
@ -92,6 +92,12 @@ for arg in '' , ,, ,,, : :: ::: \
chdir:when=65536:error=30 \
chdir:when=1+65536 \
chdir:when=1+65536:error=31 \
file,nonsense \
\!desc,nonsense \
chdir,nonsense \
\!chdir,nonsense \
1,nonsense \
\!1,nonsense \
; do
$STRACE -e fault="$arg" true 2> "$LOG" &&
fail_with "$arg"