aboutsummaryrefslogtreecommitdiffstats
path: root/csource
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2017-05-29 14:33:50 +0200
committerGitHub <noreply@github.com>2017-05-29 14:33:50 +0200
commitbaf825803c72cdc02bed92a5f84ec43482aa35d3 (patch)
treec9594f9450bb91ce03a5f671f53755c193077ef3 /csource
parent145e067777cb0d21644412548e67dcb934f1da5e (diff)
parenteaf1f711fc42235d0b9a73c6877d14b1b5244194 (diff)
Merge pull request #196 from dvyukov/executor-fault-inject3
fault injection and faster tests
Diffstat (limited to 'csource')
-rw-r--r--csource/common.go33
-rw-r--r--csource/csource.go27
-rw-r--r--csource/csource_test.go24
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)