aboutsummaryrefslogtreecommitdiffstats
path: root/csource
diff options
context:
space:
mode:
authorAndrey Konovalov <andreyknvl@google.com>2017-05-18 14:54:02 +0200
committerAndrey Konovalov <andreyknvl@google.com>2017-06-12 19:48:23 +0200
commit10c9064bfc4890e5895057021280a0558131e3eb (patch)
treed651d4ecf24acbdad5bfb26e95cd943389d4e091 /csource
parentacae98dc5463f8aaa13013aab1aa80509d800fb7 (diff)
csource: only handle SIGSEGV when necessary
Diffstat (limited to 'csource')
-rw-r--r--csource/common.go33
-rw-r--r--csource/csource.go40
-rw-r--r--csource/csource_test.go20
3 files changed, 62 insertions, 31 deletions
diff --git a/csource/common.go b/csource/common.go
index b748a555a..8d4a74146 100644
--- a/csource/common.go
+++ b/csource/common.go
@@ -116,6 +116,7 @@ void debug(const char* msg, ...)
fflush(stdout);
}
+#if defined(SYZ_EXECUTOR) || defined(SYZ_HANDLE_SEGV)
__thread int skip_segv;
__thread jmp_buf segv_env;
@@ -150,6 +151,16 @@ static void install_segv_handler()
sigaction(SIGBUS, &sa, NULL);
}
+#define NONFAILING(...) \
+ { \
+ __atomic_fetch_add(&skip_segv, 1, __ATOMIC_SEQ_CST); \
+ if (_setjmp(segv_env) == 0) { \
+ __VA_ARGS__; \
+ } \
+ __atomic_fetch_sub(&skip_segv, 1, __ATOMIC_SEQ_CST); \
+ }
+#endif
+
#if defined(SYZ_EXECUTOR) || defined(SYZ_USE_TMP_DIR)
static void use_temporary_dir()
{
@@ -164,15 +175,6 @@ static void use_temporary_dir()
}
#endif
-#define NONFAILING(...) \
- { \
- __atomic_fetch_add(&skip_segv, 1, __ATOMIC_SEQ_CST); \
- if (_setjmp(segv_env) == 0) { \
- __VA_ARGS__; \
- } \
- __atomic_fetch_sub(&skip_segv, 1, __ATOMIC_SEQ_CST); \
- }
-
#define BITMASK_LEN(type, bf_len) (type)((1ull << (bf_len)) - 1)
#define BITMASK_LEN_OFF(type, bf_off, bf_len) (type)(BITMASK_LEN(type, (bf_len)) << (bf_off))
@@ -433,8 +435,13 @@ static uintptr_t syz_extract_tcp_res(uintptr_t a0, uintptr_t a1, uintptr_t a2)
}
struct tcp_resources* res = (struct tcp_resources*)a0;
+#if defined(SYZ_EXECUTOR) || defined(SYZ_HANDLE_SEGV)
NONFAILING(res->seq = htonl((ntohl(tcphdr->seq) + (uint32_t)a1)));
NONFAILING(res->ack = htonl((ntohl(tcphdr->ack_seq) + (uint32_t)a2)));
+#else
+ res->seq = htonl((ntohl(tcphdr->seq) + (uint32_t)a1));
+ res->ack = htonl((ntohl(tcphdr->ack_seq) + (uint32_t)a2));
+#endif
debug("extracted seq: %08x\n", res->seq);
debug("extracted ack: %08x\n", res->ack);
@@ -453,7 +460,11 @@ static uintptr_t syz_open_dev(uintptr_t a0, uintptr_t a1, uintptr_t a2)
} else {
char buf[1024];
char* hash;
+#if defined(SYZ_EXECUTOR) || defined(SYZ_HANDLE_SEGV)
NONFAILING(strncpy(buf, (char*)a0, sizeof(buf)));
+#else
+ strncpy(buf, (char*)a0, sizeof(buf));
+#endif
buf[sizeof(buf) - 1] = 0;
while ((hash = strchr(buf, '#'))) {
*hash = '0' + (char)(a1 % 10);
@@ -539,6 +550,10 @@ static uintptr_t syz_fuseblk_mount(uintptr_t a0, uintptr_t a1, uintptr_t a2, uin
+#ifndef NONFAILING
+#define NONFAILING(x) { x; }
+#endif
+
const char kvm_asm16_cpl3[] = "\x0f\x20\xc0\x66\x83\xc8\x01\x0f\x22\xc0\xb8\xa0\x00\x0f\x00\xd8\xb8\x2b\x00\x8e\xd8\x8e\xc0\x8e\xe0\x8e\xe8\xbc\x00\x01\xc7\x06\x00\x01\x1d\xba\xc7\x06\x02\x01\x23\x00\xc7\x06\x04\x01\x00\x01\xc7\x06\x06\x01\x2b\x00\xcb";
const char kvm_asm32_paged[] = "\x0f\x20\xc0\x0d\x00\x00\x00\x80\x0f\x22\xc0";
const char kvm_asm32_vm86[] = "\x66\xb8\xb8\x00\x0f\x00\xd8\xea\x00\x00\x00\x00\xd0\x00";
diff --git a/csource/csource.go b/csource/csource.go
index bc50bf2ea..ccc235f7e 100644
--- a/csource/csource.go
+++ b/csource/csource.go
@@ -33,8 +33,9 @@ type Options struct {
FaultNth int
// These options allow for a more fine-tuned control over the generated C code.
- EnableTun bool
- UseTmpDir bool
+ EnableTun bool
+ UseTmpDir bool
+ HandleSegv bool
// Generate code for use with repro package to prints log messages,
// which allows to distinguish between a hang and an absent crash.
@@ -75,7 +76,9 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) {
generateTestFunc(w, opts, calls, "loop")
fmt.Fprint(w, "int main()\n{\n")
- fmt.Fprintf(w, "\tinstall_segv_handler();\n")
+ if opts.HandleSegv {
+ fmt.Fprintf(w, "\tinstall_segv_handler();\n")
+ }
if opts.UseTmpDir {
fmt.Fprintf(w, "\tuse_temporary_dir();\n")
}
@@ -87,7 +90,9 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) {
generateTestFunc(w, opts, calls, "test")
if opts.Procs <= 1 {
fmt.Fprint(w, "int main()\n{\n")
- fmt.Fprintf(w, "\tinstall_segv_handler();\n")
+ if opts.HandleSegv {
+ fmt.Fprintf(w, "\tinstall_segv_handler();\n")
+ }
if opts.UseTmpDir {
fmt.Fprintf(w, "\tuse_temporary_dir();\n")
}
@@ -100,7 +105,9 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) {
fmt.Fprint(w, "\tint i;")
fmt.Fprintf(w, "\tfor (i = 0; i < %v; i++) {\n", opts.Procs)
fmt.Fprint(w, "\t\tif (fork() == 0) {\n")
- fmt.Fprintf(w, "\t\t\tinstall_segv_handler();\n")
+ if opts.HandleSegv {
+ fmt.Fprintf(w, "\t\t\tinstall_segv_handler();\n")
+ }
if opts.UseTmpDir {
fmt.Fprintf(w, "\t\t\tuse_temporary_dir();\n")
}
@@ -136,7 +143,7 @@ func generateTestFunc(w io.Writer, opts Options, calls []string, name string) {
for _, c := range calls {
fmt.Fprintf(w, "%s", c)
}
- fmt.Fprintf(w, "}\n")
+ fmt.Fprintf(w, "}\n\n")
} else {
fmt.Fprintf(w, "void *thr(void *arg)\n{\n")
fmt.Fprintf(w, "\tswitch ((long)arg) {\n")
@@ -193,6 +200,10 @@ func generateCalls(exec []byte, opts Options) ([]string, int) {
}
return res
}
+ nonfailPre, nonfailPost := "", ""
+ if opts.HandleSegv {
+ nonfailPre, nonfailPost = "NONFAILING(", ")"
+ }
lastCall := 0
seenCall := false
var calls []string
@@ -221,12 +232,12 @@ loop:
bfOff := read()
bfLen := read()
if bfOff == 0 && bfLen == 0 {
- fmt.Fprintf(w, "\tNONFAILING(*(uint%v_t*)0x%x = (uint%v_t)0x%x);\n", size*8, addr, size*8, arg)
+ fmt.Fprintf(w, "\t%s*(uint%v_t*)0x%x = (uint%v_t)0x%x%s;\n", nonfailPre, size*8, addr, size*8, arg, nonfailPost)
} else {
- fmt.Fprintf(w, "\tNONFAILING(STORE_BY_BITMASK(uint%v_t, 0x%x, 0x%x, %v, %v));\n", size*8, addr, arg, bfOff, bfLen)
+ fmt.Fprintf(w, "\t%sSTORE_BY_BITMASK(uint%v_t, 0x%x, 0x%x, %v, %v)%s;\n", nonfailPre, size*8, addr, arg, bfOff, bfLen, nonfailPost)
}
case prog.ExecArgResult:
- fmt.Fprintf(w, "\tNONFAILING(*(uint%v_t*)0x%x = %v);\n", size*8, addr, resultRef())
+ fmt.Fprintf(w, "\t%s*(uint%v_t*)0x%x = %v%s;\n", nonfailPre, size*8, addr, resultRef(), nonfailPost)
case prog.ExecArgData:
data := exec[:size]
exec = exec[(size+7)/8*8:]
@@ -240,7 +251,7 @@ loop:
}
esc = append(esc, '\\', 'x', hex(v>>4), hex(v<<4>>4))
}
- fmt.Fprintf(w, "\tNONFAILING(memcpy((void*)0x%x, \"%s\", %v));\n", addr, esc, size)
+ fmt.Fprintf(w, "\t%smemcpy((void*)0x%x, \"%s\", %v)%s;\n", nonfailPre, addr, esc, size, nonfailPost)
case prog.ExecArgCsum:
csum_kind := read()
switch csum_kind {
@@ -254,7 +265,7 @@ loop:
chunk_size := read()
switch chunk_kind {
case prog.ExecArgCsumChunkData:
- fmt.Fprintf(w, "\tNONFAILING(csum_inet_update(&csum_%d, (const uint8_t*)0x%x, %d));\n", n, chunk_value, chunk_size)
+ fmt.Fprintf(w, "\t%scsum_inet_update(&csum_%d, (const uint8_t*)0x%x, %d)%s;\n", nonfailPre, n, chunk_value, chunk_size, nonfailPost)
case prog.ExecArgCsumChunkConst:
fmt.Fprintf(w, "\tuint%d_t csum_%d_chunk_%d = 0x%x;\n", chunk_size*8, n, i, chunk_value)
fmt.Fprintf(w, "\tcsum_inet_update(&csum_%d, (const uint8_t*)&csum_%d_chunk_%d, %d);\n", n, n, i, chunk_size)
@@ -262,7 +273,7 @@ loop:
panic(fmt.Sprintf("unknown checksum chunk kind %v", chunk_kind))
}
}
- fmt.Fprintf(w, "\tNONFAILING(*(uint16_t*)0x%x = csum_inet_digest(&csum_%d));\n", addr, n)
+ fmt.Fprintf(w, "\t%s*(uint16_t*)0x%x = csum_inet_digest(&csum_%d)%s;\n", nonfailPre, addr, n, nonfailPost)
default:
panic(fmt.Sprintf("unknown csum kind %v", csum_kind))
}
@@ -273,7 +284,7 @@ loop:
addr := read()
size := read()
fmt.Fprintf(w, "\tif (r[%v] != -1)\n", lastCall)
- fmt.Fprintf(w, "\t\tNONFAILING(r[%v] = *(uint%v_t*)0x%x);\n", n, size*8, addr)
+ fmt.Fprintf(w, "\t\t%sr[%v] = *(uint%v_t*)0x%x%s;\n", nonfailPre, n, size*8, addr, nonfailPost)
default:
// Normal syscall.
newCall()
@@ -337,6 +348,9 @@ func preprocessCommonHeader(opts Options, handled map[string]int) (string, error
if opts.UseTmpDir {
defines = append(defines, "SYZ_USE_TMP_DIR")
}
+ if opts.HandleSegv {
+ defines = append(defines, "SYZ_HANDLE_SEGV")
+ }
for name, _ := range handled {
defines = append(defines, "__NR_"+name)
}
diff --git a/csource/csource_test.go b/csource/csource_test.go
index 3e09a3019..dbecec54c 100644
--- a/csource/csource_test.go
+++ b/csource/csource_test.go
@@ -38,16 +38,18 @@ func allOptionsPermutations() []Options {
for _, opt.Fault = range []bool{false, true} {
for _, opt.EnableTun = range []bool{false, true} {
for _, opt.UseTmpDir = range []bool{false, true} {
- if opt.Collide && !opt.Threaded {
- continue
+ for _, opt.HandleSegv = 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)
}
}
}