]> granicus.if.org Git - strace/commitdiff
Fix meaning of negated sets in fault expressions
authorDmitry V. Levin <ldv@altlinux.org>
Tue, 29 Nov 2016 02:11:48 +0000 (02:11 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Tue, 29 Nov 2016 02:11:48 +0000 (02:11 +0000)
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.

syscall.c
tests/fault_syntax.test

index 12962e2caf5ed1eb013d00f20631d9ff536df555..ae145b45255fbe9415d2ab46769b0dde6087059f 100644 (file)
--- a/syscall.c
+++ b/syscall.c
@@ -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);
                        }
                }
        }
index bd306bb37440d2440bb5653401fbe9ae1995a078..cdd7931812c9e03739b9fa40486111fc23f21591 100755 (executable)
@@ -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"