From 10c9064bfc4890e5895057021280a0558131e3eb Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Thu, 18 May 2017 14:54:02 +0200 Subject: csource: only handle SIGSEGV when necessary --- csource/common.go | 33 ++++++++++++++++++++++++--------- csource/csource.go | 40 +++++++++++++++++++++++++++------------- csource/csource_test.go | 20 +++++++++++--------- 3 files changed, 62 insertions(+), 31 deletions(-) (limited to 'csource') 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) } } } -- cgit mrf-deployment