diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2017-05-29 14:33:50 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-05-29 14:33:50 +0200 |
| commit | baf825803c72cdc02bed92a5f84ec43482aa35d3 (patch) | |
| tree | c9594f9450bb91ce03a5f671f53755c193077ef3 /csource | |
| parent | 145e067777cb0d21644412548e67dcb934f1da5e (diff) | |
| parent | eaf1f711fc42235d0b9a73c6877d14b1b5244194 (diff) | |
Merge pull request #196 from dvyukov/executor-fault-inject3
fault injection and faster tests
Diffstat (limited to 'csource')
| -rw-r--r-- | csource/common.go | 33 | ||||
| -rw-r--r-- | csource/csource.go | 27 | ||||
| -rw-r--r-- | csource/csource_test.go | 24 |
3 files changed, 59 insertions, 25 deletions
diff --git a/csource/common.go b/csource/common.go index 240dff6c8..25d062821 100644 --- a/csource/common.go +++ b/csource/common.go @@ -1602,13 +1602,7 @@ static int do_sandbox_setuid(int executor_pid, bool enable_tun) } #endif -#if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NAMESPACE) -static int real_uid; -static int real_gid; -static int epid; -static bool etun; -__attribute__((aligned(64 << 10))) static char sandbox_stack[1 << 20]; - +#if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NAMESPACE) || defined(SYZ_FAULT_INJECTION) static bool write_file(const char* file, const char* what, ...) { char buf[1024]; @@ -1629,6 +1623,14 @@ static bool write_file(const char* file, const char* what, ...) close(fd); return true; } +#endif + +#if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NAMESPACE) +static int real_uid; +static int real_gid; +static int epid; +static bool etun; +__attribute__((aligned(64 << 10))) static char sandbox_stack[1 << 20]; static int namespace_sandbox_proc(void* arg) { @@ -1785,6 +1787,23 @@ static uint64_t current_time_ms() } #endif +#if defined(SYZ_EXECUTOR) || defined(SYZ_FAULT_INJECTION) +static int inject_fault(int nth) +{ + int fd; + char buf[128]; + + sprintf(buf, "/proc/self/task/%d/fail-nth", (int)syscall(SYS_gettid)); + fd = open(buf, O_RDWR); + if (fd == -1) + fail("failed to open /proc/self/task/tid/fail-nth"); + sprintf(buf, "%d", nth + 1); + if (write(fd, buf, strlen(buf)) != (ssize_t)strlen(buf)) + fail("failed to write /proc/self/task/tid/fail-nth"); + return fd; +} +#endif + #if defined(SYZ_REPEAT) static void test(); diff --git a/csource/csource.go b/csource/csource.go index 959538dbb..ab585ebec 100644 --- a/csource/csource.go +++ b/csource/csource.go @@ -22,12 +22,15 @@ import ( ) type Options struct { - Threaded bool - Collide bool - Repeat bool - Procs int - Sandbox string - Repro bool // generate code for use with repro package + Threaded bool + Collide bool + Repeat bool + Procs int + Sandbox string + Fault bool // inject fault into FaultCall/FaultNth + FaultCall int + FaultNth int + Repro bool // generate code for use with repro package } func Write(p *prog.Prog, opts Options) ([]byte, error) { @@ -65,7 +68,7 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) { fmt.Fprint(w, hdr) fmt.Fprint(w, "\n") - calls, nvar := generateCalls(exec) + calls, nvar := generateCalls(exec, opts) fmt.Fprintf(w, "long r[%v];\n", nvar) if !opts.Repeat { @@ -161,7 +164,7 @@ func generateTestFunc(w io.Writer, opts Options, calls []string, name string) { } } -func generateCalls(exec []byte) ([]string, int) { +func generateCalls(exec []byte, opts Options) ([]string, int) { read := func() uintptr { if len(exec) < 8 { panic("exec program overflow") @@ -265,6 +268,11 @@ loop: default: // Normal syscall. newCall() + if opts.Fault && opts.FaultCall == len(calls) { + fmt.Fprintf(w, "\twrite_file(\"/sys/kernel/debug/failslab/ignore-gfp-wait\", \"N\");\n") + fmt.Fprintf(w, "\twrite_file(\"/sys/kernel/debug/fail_futex/ignore-private\", \"N\");\n") + fmt.Fprintf(w, "\tinject_fault(%v);\n", opts.FaultNth) + } meta := sys.Calls[instr] fmt.Fprintf(w, "\tr[%v] = execute_syscall(__NR_%v", n, meta.CallName) nargs := read() @@ -311,6 +319,9 @@ func preprocessCommonHeader(opts Options, handled map[string]int) (string, error if opts.Repeat { defines = append(defines, "SYZ_REPEAT") } + if opts.Fault { + defines = append(defines, "SYZ_FAULT_INJECTION") + } for name, _ := range handled { defines = append(defines, "__NR_"+name) } diff --git a/csource/csource_test.go b/csource/csource_test.go index 259b5689b..78998a32f 100644 --- a/csource/csource_test.go +++ b/csource/csource_test.go @@ -15,6 +15,7 @@ import ( ) func initTest(t *testing.T) (rand.Source, int) { + t.Parallel() iters := 10 if testing.Short() { iters = 1 @@ -34,16 +35,18 @@ func allOptionsPermutations() []Options { for _, opt.Repro = range []bool{false, true} { for _, opt.Procs = range []int{1, 4} { for _, opt.Sandbox = range []string{"none", "setuid", "namespace"} { - if opt.Collide && !opt.Threaded { - continue + for _, opt.Fault = range []bool{false, true} { + if opt.Collide && !opt.Threaded { + continue + } + if !opt.Repeat && opt.Procs != 1 { + continue + } + if testing.Short() && opt.Procs != 1 { + continue + } + options = append(options, opt) } - if !opt.Repeat && opt.Procs != 1 { - continue - } - if testing.Short() && opt.Procs != 1 { - continue - } - options = append(options, opt) } } } @@ -68,11 +71,12 @@ func TestSyz(t *testing.T) { } func Test(t *testing.T) { - rs, iters := initTest(t) + rs, _ := initTest(t) syzProg := prog.GenerateAllSyzProg(rs) t.Logf("syz program:\n%s\n", syzProg.Serialize()) for i, opts := range allOptionsPermutations() { t.Run(fmt.Sprintf("%v", i), func(t *testing.T) { + rs, iters := initTest(t) t.Logf("opts: %+v", opts) for i := 0; i < iters; i++ { p := prog.Generate(rs, 10, nil) |
