From 7b43c5f9f723c6d593cb03065ea3371b86c350c7 Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Wed, 17 May 2017 17:36:31 +0200 Subject: executor: move inet checksum code under ifdef --- executor/common.h | 62 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 32 insertions(+), 30 deletions(-) (limited to 'executor/common.h') diff --git a/executor/common.h b/executor/common.h index af87856fb..46356c6a9 100644 --- a/executor/common.h +++ b/executor/common.h @@ -320,6 +320,38 @@ void debug_dump_data(const char* data, int length) } #endif // SYZ_TUN_ENABLE +#if defined(__NR_syz_emit_ethernet) || defined(__NR_syz_test) +struct csum_inet { + uint32_t acc; +}; + +void csum_inet_init(struct csum_inet* csum) +{ + csum->acc = 0; +} + +void csum_inet_update(struct csum_inet* csum, const uint8_t* data, size_t length) +{ + if (length == 0) + return; + + size_t i; + for (i = 0; i < length - 1; i += 2) + csum->acc += *(uint16_t*)&data[i]; + + if (length & 1) + csum->acc += (uint16_t)data[length - 1]; + + while (csum->acc > 0xffff) + csum->acc = (csum->acc & 0xffff) + (csum->acc >> 16); +} + +uint16_t csum_inet_digest(struct csum_inet* csum) +{ + return ~csum->acc; +} +#endif + #ifdef __NR_syz_emit_ethernet static uintptr_t syz_emit_ethernet(uintptr_t a0, uintptr_t a1) { @@ -426,36 +458,6 @@ static uintptr_t syz_extract_tcp_res(uintptr_t a0, uintptr_t a1, uintptr_t a2) } #endif -struct csum_inet { - uint32_t acc; -}; - -void csum_inet_init(struct csum_inet* csum) -{ - csum->acc = 0; -} - -void csum_inet_update(struct csum_inet* csum, const uint8_t* data, size_t length) -{ - if (length == 0) - return; - - size_t i; - for (i = 0; i < length - 1; i += 2) - csum->acc += *(uint16_t*)&data[i]; - - if (length & 1) - csum->acc += (uint16_t)data[length - 1]; - - while (csum->acc > 0xffff) - csum->acc = (csum->acc & 0xffff) + (csum->acc >> 16); -} - -uint16_t csum_inet_digest(struct csum_inet* csum) -{ - return ~csum->acc; -} - #ifdef __NR_syz_open_dev static uintptr_t syz_open_dev(uintptr_t a0, uintptr_t a1, uintptr_t a2) { -- cgit mrf-deployment From 1ab96df8855796901f133c1afab0f7384fc92eea Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Wed, 17 May 2017 18:05:28 +0200 Subject: executor: call flush_tun for repeat repros --- csource/common.go | 19 ++++++++++++------- executor/common.h | 19 ++++++++++++------- 2 files changed, 24 insertions(+), 14 deletions(-) (limited to 'executor/common.h') diff --git a/csource/common.go b/csource/common.go index e1c1863ec..09eeac8a4 100644 --- a/csource/common.go +++ b/csource/common.go @@ -368,13 +368,6 @@ int read_tun(char* data, int size) return rv; } -void flush_tun() -{ - char data[SYZ_TUN_MAX_PACKET_SIZE]; - while (read_tun(&data[0], sizeof(data)) != -1) - ; -} - static uintptr_t syz_extract_tcp_res(uintptr_t a0, uintptr_t a1, uintptr_t a2) { @@ -425,6 +418,15 @@ static uintptr_t syz_extract_tcp_res(uintptr_t a0, uintptr_t a1, uintptr_t a2) } #endif +#if defined(SYZ_TUN_ENABLE) && (defined(SYZ_EXECUTOR) || defined(SYZ_REPEAT)) +void flush_tun() +{ + char data[SYZ_TUN_MAX_PACKET_SIZE]; + while (read_tun(&data[0], sizeof(data)) != -1) + ; +} +#endif + #ifdef __NR_syz_open_dev static uintptr_t syz_open_dev(uintptr_t a0, uintptr_t a1, uintptr_t a2) { @@ -1825,6 +1827,9 @@ void loop() setpgrp(); if (chdir(cwdbuf)) fail("failed to chdir"); +#if defined(SYZ_TUN_ENABLE) + flush_tun(); +#endif test(); doexit(0); } diff --git a/executor/common.h b/executor/common.h index 46356c6a9..55ed7a73a 100644 --- a/executor/common.h +++ b/executor/common.h @@ -399,13 +399,6 @@ int read_tun(char* data, int size) return rv; } -void flush_tun() -{ - char data[SYZ_TUN_MAX_PACKET_SIZE]; - while (read_tun(&data[0], sizeof(data)) != -1) - ; -} - static uintptr_t syz_extract_tcp_res(uintptr_t a0, uintptr_t a1, uintptr_t a2) { // syz_extract_tcp_res(res ptr[out, tcp_resources], seq_inc int32, ack_inc int32) @@ -458,6 +451,15 @@ static uintptr_t syz_extract_tcp_res(uintptr_t a0, uintptr_t a1, uintptr_t a2) } #endif +#if defined(SYZ_TUN_ENABLE) && (defined(SYZ_EXECUTOR) || defined(SYZ_REPEAT)) +void flush_tun() +{ + char data[SYZ_TUN_MAX_PACKET_SIZE]; + while (read_tun(&data[0], sizeof(data)) != -1) + ; +} +#endif + #ifdef __NR_syz_open_dev static uintptr_t syz_open_dev(uintptr_t a0, uintptr_t a1, uintptr_t a2) { @@ -939,6 +941,9 @@ void loop() setpgrp(); if (chdir(cwdbuf)) fail("failed to chdir"); +#if defined(SYZ_TUN_ENABLE) + flush_tun(); +#endif test(); doexit(0); } -- cgit mrf-deployment From 7d7c9c550f5d83c652719be31a350a9f8f306b3c Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Wed, 17 May 2017 20:20:23 +0200 Subject: csource: add EnableTun option --- csource/common.go | 62 ++++++++++++++++++++++-------------------- csource/csource.go | 36 +++++++++++++------------ csource/csource_test.go | 28 ++++++++++--------- executor/common.h | 66 ++++++++++++++++++++++++--------------------- executor/executor.cc | 1 + repro/repro.go | 67 +++++++++++++++++++++++++++++++++------------- tools/syz-prog2c/prog2c.go | 2 ++ 7 files changed, 153 insertions(+), 109 deletions(-) (limited to 'executor/common.h') diff --git a/csource/common.go b/csource/common.go index 09eeac8a4..8146de3f4 100644 --- a/csource/common.go +++ b/csource/common.go @@ -167,10 +167,6 @@ static void install_segv_handler() *(type*)(addr) = new_val; \ } -#if defined(__NR_syz_emit_ethernet) || defined(__NR_syz_extract_tcp_res) -#define SYZ_TUN_ENABLE -#endif - #ifdef SYZ_TUN_ENABLE static void vsnprintf_check(char* str, size_t size, const char* format, va_list args) { @@ -279,6 +275,17 @@ static void setup_tun(uint64_t pid, bool enable_tun) initialize_tun(pid); } +int read_tun(char* data, int size) +{ + int rv = read(tunfd, data, size); + if (rv < 0) { + if (errno == EAGAIN) + return -1; + fail("tun: read failed with %d, errno: %d", rv, errno); + } + return rv; +} + void debug_dump_data(const char* data, int length) { int i; @@ -292,7 +299,7 @@ void debug_dump_data(const char* data, int length) } #endif -#if defined(__NR_syz_emit_ethernet) || defined(__NR_syz_test) +#if (defined(__NR_syz_emit_ethernet) && defined(SYZ_TUN_ENABLE)) || defined(__NR_syz_test) struct csum_inet { uint32_t acc; }; @@ -324,7 +331,7 @@ uint16_t csum_inet_digest(struct csum_inet* csum) } #endif -#ifdef __NR_syz_emit_ethernet +#if defined(__NR_syz_emit_ethernet) && defined(SYZ_TUN_ENABLE) static uintptr_t syz_emit_ethernet(uintptr_t a0, uintptr_t a1) { @@ -338,7 +345,16 @@ static uintptr_t syz_emit_ethernet(uintptr_t a0, uintptr_t a1) } #endif -#ifdef __NR_syz_extract_tcp_res +#if (defined(SYZ_EXECUTOR) || defined(SYZ_REPEAT)) && defined(SYZ_TUN_ENABLE) +void flush_tun() +{ + char data[SYZ_TUN_MAX_PACKET_SIZE]; + while (read_tun(&data[0], sizeof(data)) != -1) + ; +} +#endif + +#if defined(__NR_syz_extract_tcp_res) && defined(SYZ_TUN_ENABLE) struct ipv6hdr { __u8 priority : 4, version : 4; @@ -357,17 +373,6 @@ struct tcp_resources { int32_t ack; }; -int read_tun(char* data, int size) -{ - int rv = read(tunfd, data, size); - if (rv < 0) { - if (errno == EAGAIN) - return -1; - fail("tun: read failed with %d, errno: %d", rv, errno); - } - return rv; -} - static uintptr_t syz_extract_tcp_res(uintptr_t a0, uintptr_t a1, uintptr_t a2) { @@ -418,15 +423,6 @@ static uintptr_t syz_extract_tcp_res(uintptr_t a0, uintptr_t a1, uintptr_t a2) } #endif -#if defined(SYZ_TUN_ENABLE) && (defined(SYZ_EXECUTOR) || defined(SYZ_REPEAT)) -void flush_tun() -{ - char data[SYZ_TUN_MAX_PACKET_SIZE]; - while (read_tun(&data[0], sizeof(data)) != -1) - ; -} -#endif - #ifdef __NR_syz_open_dev static uintptr_t syz_open_dev(uintptr_t a0, uintptr_t a1, uintptr_t a2) { @@ -1505,13 +1501,21 @@ static uintptr_t execute_syscall(int nr, uintptr_t a0, uintptr_t a1, uintptr_t a case __NR_syz_fuseblk_mount: return syz_fuseblk_mount(a0, a1, a2, a3, a4, a5, a6, a7); #endif -#ifdef __NR_syz_emit_ethernet +#if defined(__NR_syz_emit_ethernet) case __NR_syz_emit_ethernet: +#if defined(SYZ_TUN_ENABLE) return syz_emit_ethernet(a0, a1); +#else + return 0; +#endif #endif -#ifdef __NR_syz_extract_tcp_res +#if defined(__NR_syz_extract_tcp_res) case __NR_syz_extract_tcp_res: +#if defined(SYZ_TUN_ENABLE) return syz_extract_tcp_res(a0, a1, a2); +#else + return 0; +#endif #endif #ifdef __NR_syz_kvm_setup_cpu case __NR_syz_kvm_setup_cpu: diff --git a/csource/csource.go b/csource/csource.go index ab585ebec..cc4d0d944 100644 --- a/csource/csource.go +++ b/csource/csource.go @@ -22,15 +22,22 @@ import ( ) type Options struct { - Threaded bool - Collide bool - Repeat bool - Procs int - Sandbox string + 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 + + // These options allow for a more fine-tuned control over the generated C code. + EnableTun bool + + // Generate code for use with repro package to prints log messages, + // which allows to distinguish between a hang and an absent crash. + Repro bool } func Write(p *prog.Prog, opts Options) ([]byte, error) { @@ -53,14 +60,6 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) { } fmt.Fprintf(w, "\n") - enableTun := "false" - if _, ok := handled["syz_emit_ethernet"]; ok { - enableTun = "true" - } - if _, ok := handled["syz_extract_tcp_res"]; ok { - enableTun = "true" - } - hdr, err := preprocessCommonHeader(opts, handled) if err != nil { return nil, err @@ -76,7 +75,7 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) { fmt.Fprint(w, "int main()\n{\n") fmt.Fprintf(w, "\tsetup_main_process();\n") - fmt.Fprintf(w, "\tint pid = do_sandbox_%v(0, %v);\n", opts.Sandbox, enableTun) + fmt.Fprintf(w, "\tint pid = do_sandbox_%v(0, %v);\n", opts.Sandbox, opts.EnableTun) fmt.Fprint(w, "\tint status = 0;\n") fmt.Fprint(w, "\twhile (waitpid(pid, &status, __WALL) != pid) {}\n") fmt.Fprint(w, "\treturn 0;\n}\n") @@ -85,7 +84,7 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) { if opts.Procs <= 1 { fmt.Fprint(w, "int main()\n{\n") fmt.Fprintf(w, "\tsetup_main_process();\n") - fmt.Fprintf(w, "\tint pid = do_sandbox_%v(0, %v);\n", opts.Sandbox, enableTun) + fmt.Fprintf(w, "\tint pid = do_sandbox_%v(0, %v);\n", opts.Sandbox, opts.EnableTun) fmt.Fprint(w, "\tint status = 0;\n") fmt.Fprint(w, "\twhile (waitpid(pid, &status, __WALL) != pid) {}\n") fmt.Fprint(w, "\treturn 0;\n}\n") @@ -95,7 +94,7 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) { 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\tsetup_main_process();\n") - fmt.Fprintf(w, "\t\t\tint pid = do_sandbox_%v(i, %v);\n", opts.Sandbox, enableTun) + fmt.Fprintf(w, "\t\t\tint pid = do_sandbox_%v(i, %v);\n", opts.Sandbox, opts.EnableTun) fmt.Fprint(w, "\t\t\tint status = 0;\n") fmt.Fprint(w, "\t\t\twhile (waitpid(pid, &status, __WALL) != pid) {}\n") fmt.Fprint(w, "\t\t\treturn 0;\n") @@ -322,6 +321,9 @@ func preprocessCommonHeader(opts Options, handled map[string]int) (string, error if opts.Fault { defines = append(defines, "SYZ_FAULT_INJECTION") } + if opts.EnableTun { + defines = append(defines, "SYZ_TUN_ENABLE") + } for name, _ := range handled { defines = append(defines, "__NR_"+name) } diff --git a/csource/csource_test.go b/csource/csource_test.go index abff96f72..8ca7bb5ce 100644 --- a/csource/csource_test.go +++ b/csource/csource_test.go @@ -32,20 +32,22 @@ func allOptionsPermutations() []Options { for _, opt.Threaded = range []bool{false, true} { for _, opt.Collide = range []bool{false, true} { for _, opt.Repeat = range []bool{false, true} { - for _, opt.Repro = range []bool{false, true} { - for _, opt.Procs = range []int{1, 4} { - for _, opt.Sandbox = range []string{"none", "setuid", "namespace"} { - for _, opt.Fault = range []bool{false, true} { - if opt.Collide && !opt.Threaded { - continue + for _, opt.Procs = range []int{1, 4} { + for _, opt.Sandbox = range []string{"none", "setuid", "namespace"} { + for _, opt.Repro = range []bool{false, true} { + for _, opt.EnableTun = range []bool{false, true} { + 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) } } } diff --git a/executor/common.h b/executor/common.h index 55ed7a73a..d7b403554 100644 --- a/executor/common.h +++ b/executor/common.h @@ -189,10 +189,6 @@ static void install_segv_handler() *(type*)(addr) = new_val; \ } -#if defined(__NR_syz_emit_ethernet) || defined(__NR_syz_extract_tcp_res) -#define SYZ_TUN_ENABLE -#endif - #ifdef SYZ_TUN_ENABLE static void vsnprintf_check(char* str, size_t size, const char* format, va_list args) { @@ -307,6 +303,17 @@ static void setup_tun(uint64_t pid, bool enable_tun) initialize_tun(pid); } +int read_tun(char* data, int size) +{ + int rv = read(tunfd, data, size); + if (rv < 0) { + if (errno == EAGAIN) + return -1; + fail("tun: read failed with %d, errno: %d", rv, errno); + } + return rv; +} + void debug_dump_data(const char* data, int length) { int i; @@ -320,7 +327,7 @@ void debug_dump_data(const char* data, int length) } #endif // SYZ_TUN_ENABLE -#if defined(__NR_syz_emit_ethernet) || defined(__NR_syz_test) +#if (defined(__NR_syz_emit_ethernet) && defined(SYZ_TUN_ENABLE)) || defined(__NR_syz_test) struct csum_inet { uint32_t acc; }; @@ -352,7 +359,7 @@ uint16_t csum_inet_digest(struct csum_inet* csum) } #endif -#ifdef __NR_syz_emit_ethernet +#if defined(__NR_syz_emit_ethernet) && defined(SYZ_TUN_ENABLE) static uintptr_t syz_emit_ethernet(uintptr_t a0, uintptr_t a1) { // syz_emit_ethernet(len len[packet], packet ptr[in, eth_packet]) @@ -367,7 +374,16 @@ static uintptr_t syz_emit_ethernet(uintptr_t a0, uintptr_t a1) } #endif -#ifdef __NR_syz_extract_tcp_res +#if (defined(SYZ_EXECUTOR) || defined(SYZ_REPEAT)) && defined(SYZ_TUN_ENABLE) +void flush_tun() +{ + char data[SYZ_TUN_MAX_PACKET_SIZE]; + while (read_tun(&data[0], sizeof(data)) != -1) + ; +} +#endif + +#if defined(__NR_syz_extract_tcp_res) && defined(SYZ_TUN_ENABLE) // Can't include , since it causes // conflicts due to some structs redefinition. struct ipv6hdr { @@ -388,17 +404,6 @@ struct tcp_resources { int32_t ack; }; -int read_tun(char* data, int size) -{ - int rv = read(tunfd, data, size); - if (rv < 0) { - if (errno == EAGAIN) - return -1; - fail("tun: read failed with %d, errno: %d", rv, errno); - } - return rv; -} - static uintptr_t syz_extract_tcp_res(uintptr_t a0, uintptr_t a1, uintptr_t a2) { // syz_extract_tcp_res(res ptr[out, tcp_resources], seq_inc int32, ack_inc int32) @@ -451,15 +456,6 @@ static uintptr_t syz_extract_tcp_res(uintptr_t a0, uintptr_t a1, uintptr_t a2) } #endif -#if defined(SYZ_TUN_ENABLE) && (defined(SYZ_EXECUTOR) || defined(SYZ_REPEAT)) -void flush_tun() -{ - char data[SYZ_TUN_MAX_PACKET_SIZE]; - while (read_tun(&data[0], sizeof(data)) != -1) - ; -} -#endif - #ifdef __NR_syz_open_dev static uintptr_t syz_open_dev(uintptr_t a0, uintptr_t a1, uintptr_t a2) { @@ -597,14 +593,22 @@ static uintptr_t execute_syscall(int nr, uintptr_t a0, uintptr_t a1, uintptr_t a case __NR_syz_fuseblk_mount: return syz_fuseblk_mount(a0, a1, a2, a3, a4, a5, a6, a7); #endif -#ifdef __NR_syz_emit_ethernet +#if defined(__NR_syz_emit_ethernet) case __NR_syz_emit_ethernet: +#if defined(SYZ_TUN_ENABLE) return syz_emit_ethernet(a0, a1); -#endif -#ifdef __NR_syz_extract_tcp_res +#else + return 0; +#endif // defined(SYZ_TUN_ENABLE) +#endif // defined(__NR_syz_emit_ethernet) +#if defined(__NR_syz_extract_tcp_res) case __NR_syz_extract_tcp_res: +#if defined(SYZ_TUN_ENABLE) return syz_extract_tcp_res(a0, a1, a2); -#endif +#else + return 0; +#endif // defined(SYZ_TUN_ENABLE) +#endif // defined(__NR_syz_extract_tcp_res) #ifdef __NR_syz_kvm_setup_cpu case __NR_syz_kvm_setup_cpu: return syz_kvm_setup_cpu(a0, a1, a2, a3, a4, a5, a6, a7); diff --git a/executor/executor.cc b/executor/executor.cc index 044410792..800ac932e 100644 --- a/executor/executor.cc +++ b/executor/executor.cc @@ -31,6 +31,7 @@ #include "syscalls.h" #define SYZ_EXECUTOR +#define SYZ_TUN_ENABLE #include "common.h" #define KCOV_INIT_TRACE _IOR('c', 1, unsigned long long) diff --git a/repro/repro.go b/repro/repro.go index c2f9e52a7..2f713c89f 100644 --- a/repro/repro.go +++ b/repro/repro.go @@ -151,12 +151,13 @@ func (ctx *context) repro(entries []*prog.LogEntry, crashStart int) (*Result, er } Logf(2, "reproducing crash '%v': suspecting %v programs", ctx.crashDesc, len(suspected)) opts := csource.Options{ - Threaded: true, - Collide: true, - Repeat: true, - Procs: ctx.cfg.Procs, - Sandbox: ctx.cfg.Sandbox, - Repro: true, + Threaded: true, + Collide: true, + Repeat: true, + Procs: ctx.cfg.Procs, + Sandbox: ctx.cfg.Sandbox, + EnableTun: true, + Repro: true, } // Execute the suspected programs. // We first try to execute each program for 10 seconds, that should detect simple crashes @@ -264,24 +265,29 @@ func (ctx *context) repro(entries []*prog.LogEntry, crashStart int) (*Result, er } } - src, err := csource.Write(res.Prog, res.Opts) + // Try triggering crash with a C reproducer. + crashed, err = ctx.testCProg(res.Prog, duration, res.Opts) if err != nil { return res, err } - srcf, err := fileutil.WriteTempFile(src) - if err != nil { - return res, err - } - bin, err := csource.Build("c", srcf) - if err != nil { - return res, err + res.CRepro = crashed + if !crashed { + return res, nil } - defer os.Remove(bin) - crashed, err = ctx.testBin(bin, duration) - if err != nil { - return res, err + + // Try to simplify the C reproducer. + if res.Opts.EnableTun { + opts = res.Opts + opts.EnableTun = false + crashed, err := ctx.testCProg(res.Prog, duration, opts) + if err != nil { + return res, err + } + if crashed { + res.Opts = opts + } } - res.CRepro = crashed + return res, nil } @@ -317,6 +323,29 @@ func (ctx *context) testProg(p *prog.Prog, duration time.Duration, opts csource. return ctx.testImpl(inst.Instance, command, duration) } +func (ctx *context) testCProg(p *prog.Prog, duration time.Duration, opts csource.Options) (crashed bool, err error) { + src, err := csource.Write(p, opts) + if err != nil { + return false, err + } + srcf, err := fileutil.WriteTempFile(src) + if err != nil { + return false, err + } + bin, err := csource.Build("c", srcf) + if err != nil { + return false, err + } + defer os.Remove(bin) + Logf(2, "reproducing crash '%v': testing compiled C program (duration=%v, %+v): %s", + ctx.crashDesc, duration, opts, p) + crashed, err = ctx.testBin(bin, duration) + if err != nil { + return false, err + } + return crashed, nil +} + func (ctx *context) testBin(bin string, duration time.Duration) (crashed bool, err error) { inst := <-ctx.instances if inst == nil { diff --git a/tools/syz-prog2c/prog2c.go b/tools/syz-prog2c/prog2c.go index 5cdec11f2..d0d81be3b 100644 --- a/tools/syz-prog2c/prog2c.go +++ b/tools/syz-prog2c/prog2c.go @@ -22,6 +22,7 @@ var ( flagProg = flag.String("prog", "", "file with program to convert (required)") flagFaultCall = flag.Int("fault_call", -1, "inject fault into this call (0-based)") flagFaultNth = flag.Int("fault_nth", 0, "inject fault on n-th operation (0-based)") + flagEnableTun = flag.Bool("tun", false, "set up TUN/TAP interface") ) func main() { @@ -49,6 +50,7 @@ func main() { Fault: *flagFaultCall >= 0, FaultCall: *flagFaultCall, FaultNth: *flagFaultNth, + EnableTun: *flagEnableTun, Repro: false, } src, err := csource.Write(p, opts) -- cgit mrf-deployment From e7366c123e8e62cab5e70998b56e832c77178a59 Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Wed, 17 May 2017 20:35:50 +0200 Subject: executor: split setup_main_process into smaller functions --- csource/common.go | 36 +++++++++++++++++------------------- csource/csource.go | 9 ++++++--- executor/common.h | 43 +++++++++++++++++++++---------------------- executor/executor.cc | 3 ++- 4 files changed, 46 insertions(+), 45 deletions(-) (limited to 'executor/common.h') diff --git a/csource/common.go b/csource/common.go index 8146de3f4..048df6f52 100644 --- a/csource/common.go +++ b/csource/common.go @@ -137,6 +137,12 @@ static void segv_handler(int sig, siginfo_t* info, void* uctx) static void install_segv_handler() { struct sigaction sa; + + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = SIG_IGN; + syscall(SYS_rt_sigaction, 0x20, &sa, NULL, 8); + syscall(SYS_rt_sigaction, 0x21, &sa, NULL, 8); + memset(&sa, 0, sizeof(sa)); sa.sa_sigaction = segv_handler; sa.sa_flags = SA_NODEFER | SA_SIGINFO; @@ -144,6 +150,17 @@ static void install_segv_handler() sigaction(SIGBUS, &sa, NULL); } +static void use_temporary_dir() { + char tmpdir_template[] = "./syzkaller.XXXXXX"; + char* tmpdir = mkdtemp(tmpdir_template); + if (!tmpdir) + fail("failed to mkdtemp"); + if (chmod(tmpdir, 0777)) + fail("failed to chmod"); + if (chdir(tmpdir)) + fail("failed to chdir"); +} + #define NONFAILING(...) \ { \ __atomic_fetch_add(&skip_segv, 1, __ATOMIC_SEQ_CST); \ @@ -1524,25 +1541,6 @@ static uintptr_t execute_syscall(int nr, uintptr_t a0, uintptr_t a1, uintptr_t a } } -static void setup_main_process() -{ - struct sigaction sa; - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = SIG_IGN; - syscall(SYS_rt_sigaction, 0x20, &sa, NULL, 8); - syscall(SYS_rt_sigaction, 0x21, &sa, NULL, 8); - install_segv_handler(); - - char tmpdir_template[] = "./syzkaller.XXXXXX"; - char* tmpdir = mkdtemp(tmpdir_template); - if (!tmpdir) - fail("failed to mkdtemp"); - if (chmod(tmpdir, 0777)) - fail("failed to chmod"); - if (chdir(tmpdir)) - fail("failed to chdir"); -} - static void loop(); static void sandbox_common() diff --git a/csource/csource.go b/csource/csource.go index cc4d0d944..b41c5ca11 100644 --- a/csource/csource.go +++ b/csource/csource.go @@ -74,7 +74,8 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) { generateTestFunc(w, opts, calls, "loop") fmt.Fprint(w, "int main()\n{\n") - fmt.Fprintf(w, "\tsetup_main_process();\n") + fmt.Fprintf(w, "\tinstall_segv_handler();\n") + fmt.Fprintf(w, "\tuse_temporary_dir();\n") fmt.Fprintf(w, "\tint pid = do_sandbox_%v(0, %v);\n", opts.Sandbox, opts.EnableTun) fmt.Fprint(w, "\tint status = 0;\n") fmt.Fprint(w, "\twhile (waitpid(pid, &status, __WALL) != pid) {}\n") @@ -83,7 +84,8 @@ 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, "\tsetup_main_process();\n") + fmt.Fprintf(w, "\tinstall_segv_handler();\n") + fmt.Fprintf(w, "\tuse_temporary_dir();\n") fmt.Fprintf(w, "\tint pid = do_sandbox_%v(0, %v);\n", opts.Sandbox, opts.EnableTun) fmt.Fprint(w, "\tint status = 0;\n") fmt.Fprint(w, "\twhile (waitpid(pid, &status, __WALL) != pid) {}\n") @@ -93,7 +95,8 @@ 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\tsetup_main_process();\n") + fmt.Fprintf(w, "\t\t\tinstall_segv_handler();\n") + fmt.Fprintf(w, "\t\t\tuse_temporary_dir();\n") fmt.Fprintf(w, "\t\t\tint pid = do_sandbox_%v(i, %v);\n", opts.Sandbox, opts.EnableTun) fmt.Fprint(w, "\t\t\tint status = 0;\n") fmt.Fprint(w, "\t\t\twhile (waitpid(pid, &status, __WALL) != pid) {}\n") diff --git a/executor/common.h b/executor/common.h index d7b403554..92467dc26 100644 --- a/executor/common.h +++ b/executor/common.h @@ -159,6 +159,15 @@ static void segv_handler(int sig, siginfo_t* info, void* uctx) static void install_segv_handler() { struct sigaction sa; + + // Don't need that SIGCANCEL/SIGSETXID glibc stuff. + // SIGCANCEL sent to main thread causes it to exit + // without bringing down the whole group. + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = SIG_IGN; + syscall(SYS_rt_sigaction, 0x20, &sa, NULL, 8); + syscall(SYS_rt_sigaction, 0x21, &sa, NULL, 8); + memset(&sa, 0, sizeof(sa)); sa.sa_sigaction = segv_handler; sa.sa_flags = SA_NODEFER | SA_SIGINFO; @@ -166,6 +175,18 @@ static void install_segv_handler() sigaction(SIGBUS, &sa, NULL); } +static void use_temporary_dir() +{ + char tmpdir_template[] = "./syzkaller.XXXXXX"; + char* tmpdir = mkdtemp(tmpdir_template); + if (!tmpdir) + fail("failed to mkdtemp"); + if (chmod(tmpdir, 0777)) + fail("failed to chmod"); + if (chdir(tmpdir)) + fail("failed to chdir"); +} + #define NONFAILING(...) \ { \ __atomic_fetch_add(&skip_segv, 1, __ATOMIC_SEQ_CST); \ @@ -616,28 +637,6 @@ static uintptr_t execute_syscall(int nr, uintptr_t a0, uintptr_t a1, uintptr_t a } } -static void setup_main_process() -{ - // Don't need that SIGCANCEL/SIGSETXID glibc stuff. - // SIGCANCEL sent to main thread causes it to exit - // without bringing down the whole group. - struct sigaction sa; - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = SIG_IGN; - syscall(SYS_rt_sigaction, 0x20, &sa, NULL, 8); - syscall(SYS_rt_sigaction, 0x21, &sa, NULL, 8); - install_segv_handler(); - - char tmpdir_template[] = "./syzkaller.XXXXXX"; - char* tmpdir = mkdtemp(tmpdir_template); - if (!tmpdir) - fail("failed to mkdtemp"); - if (chmod(tmpdir, 0777)) - fail("failed to chmod"); - if (chdir(tmpdir)) - fail("failed to chdir"); -} - static void loop(); static void sandbox_common() diff --git a/executor/executor.cc b/executor/executor.cc index 800ac932e..04624cdc8 100644 --- a/executor/executor.cc +++ b/executor/executor.cc @@ -186,7 +186,8 @@ int main(int argc, char** argv) uint64_t executor_pid = *((uint64_t*)input_data + 1); cover_open(); - setup_main_process(); + install_segv_handler(); + use_temporary_dir(); int pid = -1; switch (flag_sandbox) { -- cgit mrf-deployment From 5597911fbf26237b9d11a0f6293e4b52b2d9069c Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Thu, 18 May 2017 14:26:02 +0200 Subject: csource: use tmp dir only when necessary --- csource/common.go | 5 ++++- csource/csource.go | 16 +++++++++++++--- csource/csource_test.go | 24 +++++++++++++----------- executor/common.h | 2 ++ repro/repro.go | 12 ++++++++++++ tools/syz-prog2c/prog2c.go | 2 ++ 6 files changed, 46 insertions(+), 15 deletions(-) (limited to 'executor/common.h') diff --git a/csource/common.go b/csource/common.go index 048df6f52..8fa531598 100644 --- a/csource/common.go +++ b/csource/common.go @@ -150,7 +150,9 @@ static void install_segv_handler() sigaction(SIGBUS, &sa, NULL); } -static void use_temporary_dir() { +#if defined(SYZ_EXECUTOR) || defined(SYZ_USE_TMP_DIR) +static void use_temporary_dir() +{ char tmpdir_template[] = "./syzkaller.XXXXXX"; char* tmpdir = mkdtemp(tmpdir_template); if (!tmpdir) @@ -160,6 +162,7 @@ static void use_temporary_dir() { if (chdir(tmpdir)) fail("failed to chdir"); } +#endif #define NONFAILING(...) \ { \ diff --git a/csource/csource.go b/csource/csource.go index b41c5ca11..bc50bf2ea 100644 --- a/csource/csource.go +++ b/csource/csource.go @@ -34,6 +34,7 @@ type Options struct { // These options allow for a more fine-tuned control over the generated C code. EnableTun bool + UseTmpDir 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) { fmt.Fprint(w, "int main()\n{\n") fmt.Fprintf(w, "\tinstall_segv_handler();\n") - fmt.Fprintf(w, "\tuse_temporary_dir();\n") + if opts.UseTmpDir { + fmt.Fprintf(w, "\tuse_temporary_dir();\n") + } fmt.Fprintf(w, "\tint pid = do_sandbox_%v(0, %v);\n", opts.Sandbox, opts.EnableTun) fmt.Fprint(w, "\tint status = 0;\n") fmt.Fprint(w, "\twhile (waitpid(pid, &status, __WALL) != pid) {}\n") @@ -85,7 +88,9 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) { if opts.Procs <= 1 { fmt.Fprint(w, "int main()\n{\n") fmt.Fprintf(w, "\tinstall_segv_handler();\n") - fmt.Fprintf(w, "\tuse_temporary_dir();\n") + if opts.UseTmpDir { + fmt.Fprintf(w, "\tuse_temporary_dir();\n") + } fmt.Fprintf(w, "\tint pid = do_sandbox_%v(0, %v);\n", opts.Sandbox, opts.EnableTun) fmt.Fprint(w, "\tint status = 0;\n") fmt.Fprint(w, "\twhile (waitpid(pid, &status, __WALL) != pid) {}\n") @@ -96,7 +101,9 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) { 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") - fmt.Fprintf(w, "\t\t\tuse_temporary_dir();\n") + if opts.UseTmpDir { + fmt.Fprintf(w, "\t\t\tuse_temporary_dir();\n") + } fmt.Fprintf(w, "\t\t\tint pid = do_sandbox_%v(i, %v);\n", opts.Sandbox, opts.EnableTun) fmt.Fprint(w, "\t\t\tint status = 0;\n") fmt.Fprint(w, "\t\t\twhile (waitpid(pid, &status, __WALL) != pid) {}\n") @@ -327,6 +334,9 @@ func preprocessCommonHeader(opts Options, handled map[string]int) (string, error if opts.EnableTun { defines = append(defines, "SYZ_TUN_ENABLE") } + if opts.UseTmpDir { + defines = append(defines, "SYZ_USE_TMP_DIR") + } for name, _ := range handled { defines = append(defines, "__NR_"+name) } diff --git a/csource/csource_test.go b/csource/csource_test.go index 8ca7bb5ce..3e09a3019 100644 --- a/csource/csource_test.go +++ b/csource/csource_test.go @@ -35,18 +35,20 @@ func allOptionsPermutations() []Options { for _, opt.Procs = range []int{1, 4} { for _, opt.Sandbox = range []string{"none", "setuid", "namespace"} { for _, opt.Repro = range []bool{false, true} { - for _, opt.EnableTun = range []bool{false, true} { - for _, opt.Fault = range []bool{false, true} { - if opt.Collide && !opt.Threaded { - continue + 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 + } + 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) } } } diff --git a/executor/common.h b/executor/common.h index 92467dc26..99c3fb9f3 100644 --- a/executor/common.h +++ b/executor/common.h @@ -175,6 +175,7 @@ static void install_segv_handler() sigaction(SIGBUS, &sa, NULL); } +#if defined(SYZ_EXECUTOR) || defined(SYZ_USE_TMP_DIR) static void use_temporary_dir() { char tmpdir_template[] = "./syzkaller.XXXXXX"; @@ -186,6 +187,7 @@ static void use_temporary_dir() if (chdir(tmpdir)) fail("failed to chdir"); } +#endif #define NONFAILING(...) \ { \ diff --git a/repro/repro.go b/repro/repro.go index 2f713c89f..3ae553bac 100644 --- a/repro/repro.go +++ b/repro/repro.go @@ -157,6 +157,7 @@ func (ctx *context) repro(entries []*prog.LogEntry, crashStart int) (*Result, er Procs: ctx.cfg.Procs, Sandbox: ctx.cfg.Sandbox, EnableTun: true, + UseTmpDir: true, Repro: true, } // Execute the suspected programs. @@ -287,6 +288,17 @@ func (ctx *context) repro(entries []*prog.LogEntry, crashStart int) (*Result, er res.Opts = opts } } + if res.Opts.UseTmpDir { + opts = res.Opts + opts.UseTmpDir = false + crashed, err := ctx.testCProg(res.Prog, duration, opts) + if err != nil { + return res, err + } + if crashed { + res.Opts = opts + } + } return res, nil } diff --git a/tools/syz-prog2c/prog2c.go b/tools/syz-prog2c/prog2c.go index d0d81be3b..878772d42 100644 --- a/tools/syz-prog2c/prog2c.go +++ b/tools/syz-prog2c/prog2c.go @@ -23,6 +23,7 @@ var ( flagFaultCall = flag.Int("fault_call", -1, "inject fault into this call (0-based)") flagFaultNth = flag.Int("fault_nth", 0, "inject fault on n-th operation (0-based)") flagEnableTun = flag.Bool("tun", false, "set up TUN/TAP interface") + flagUseTmpDir = flag.Bool("tmpdir", false, "create a temporary dir and execute inside it") ) func main() { @@ -51,6 +52,7 @@ func main() { FaultCall: *flagFaultCall, FaultNth: *flagFaultNth, EnableTun: *flagEnableTun, + UseTmpDir: *flagUseTmpDir, Repro: false, } src, err := csource.Write(p, opts) -- cgit mrf-deployment From acae98dc5463f8aaa13013aab1aa80509d800fb7 Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Thu, 18 May 2017 14:36:53 +0200 Subject: executor: don't define SYZ_ENABLE_TUN in executor --- csource/common.go | 22 +++++++++++----------- executor/common.h | 32 ++++++++++++++++---------------- executor/executor.cc | 1 - 3 files changed, 27 insertions(+), 28 deletions(-) (limited to 'executor/common.h') diff --git a/csource/common.go b/csource/common.go index 8fa531598..b748a555a 100644 --- a/csource/common.go +++ b/csource/common.go @@ -187,7 +187,7 @@ static void use_temporary_dir() *(type*)(addr) = new_val; \ } -#ifdef SYZ_TUN_ENABLE +#if defined(SYZ_EXECUTOR) || defined(SYZ_TUN_ENABLE) static void vsnprintf_check(char* str, size_t size, const char* format, va_list args) { int rv; @@ -319,7 +319,7 @@ void debug_dump_data(const char* data, int length) } #endif -#if (defined(__NR_syz_emit_ethernet) && defined(SYZ_TUN_ENABLE)) || defined(__NR_syz_test) +#if defined(SYZ_EXECUTOR) || (defined(__NR_syz_emit_ethernet) && defined(SYZ_TUN_ENABLE)) || defined(__NR_syz_test) struct csum_inet { uint32_t acc; }; @@ -351,7 +351,7 @@ uint16_t csum_inet_digest(struct csum_inet* csum) } #endif -#if defined(__NR_syz_emit_ethernet) && defined(SYZ_TUN_ENABLE) +#if defined(SYZ_EXECUTOR) || (defined(__NR_syz_emit_ethernet) && defined(SYZ_TUN_ENABLE)) static uintptr_t syz_emit_ethernet(uintptr_t a0, uintptr_t a1) { @@ -365,7 +365,7 @@ static uintptr_t syz_emit_ethernet(uintptr_t a0, uintptr_t a1) } #endif -#if (defined(SYZ_EXECUTOR) || defined(SYZ_REPEAT)) && defined(SYZ_TUN_ENABLE) +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_TUN_ENABLE)) void flush_tun() { char data[SYZ_TUN_MAX_PACKET_SIZE]; @@ -374,7 +374,7 @@ void flush_tun() } #endif -#if defined(__NR_syz_extract_tcp_res) && defined(SYZ_TUN_ENABLE) +#if defined(SYZ_EXECUTOR) || (defined(__NR_syz_extract_tcp_res) && defined(SYZ_TUN_ENABLE)) struct ipv6hdr { __u8 priority : 4, version : 4; @@ -1523,7 +1523,7 @@ static uintptr_t execute_syscall(int nr, uintptr_t a0, uintptr_t a1, uintptr_t a #endif #if defined(__NR_syz_emit_ethernet) case __NR_syz_emit_ethernet: -#if defined(SYZ_TUN_ENABLE) +#if defined(SYZ_EXECUTOR) || defined(SYZ_TUN_ENABLE) return syz_emit_ethernet(a0, a1); #else return 0; @@ -1531,7 +1531,7 @@ static uintptr_t execute_syscall(int nr, uintptr_t a0, uintptr_t a1, uintptr_t a #endif #if defined(__NR_syz_extract_tcp_res) case __NR_syz_extract_tcp_res: -#if defined(SYZ_TUN_ENABLE) +#if defined(SYZ_EXECUTOR) || defined(SYZ_TUN_ENABLE) return syz_extract_tcp_res(a0, a1, a2); #else return 0; @@ -1575,7 +1575,7 @@ static int do_sandbox_none(int executor_pid, bool enable_tun) return pid; sandbox_common(); -#ifdef SYZ_TUN_ENABLE +#if defined(SYZ_EXECUTOR) || defined(SYZ_TUN_ENABLE) setup_tun(executor_pid, enable_tun); #endif @@ -1592,7 +1592,7 @@ static int do_sandbox_setuid(int executor_pid, bool enable_tun) return pid; sandbox_common(); -#ifdef SYZ_TUN_ENABLE +#if defined(SYZ_EXECUTOR) || defined(SYZ_TUN_ENABLE) setup_tun(executor_pid, enable_tun); #endif @@ -1651,7 +1651,7 @@ static int namespace_sandbox_proc(void* arg) if (!write_file("/proc/self/gid_map", "0 %d 1\n", real_gid)) fail("write of /proc/self/gid_map failed"); -#ifdef SYZ_TUN_ENABLE +#if defined(SYZ_EXECUTOR) || defined(SYZ_TUN_ENABLE) setup_tun(epid, etun); #endif @@ -1832,7 +1832,7 @@ void loop() setpgrp(); if (chdir(cwdbuf)) fail("failed to chdir"); -#if defined(SYZ_TUN_ENABLE) +#ifdef SYZ_TUN_ENABLE flush_tun(); #endif test(); diff --git a/executor/common.h b/executor/common.h index 99c3fb9f3..5041aaf7b 100644 --- a/executor/common.h +++ b/executor/common.h @@ -212,7 +212,7 @@ static void use_temporary_dir() *(type*)(addr) = new_val; \ } -#ifdef SYZ_TUN_ENABLE +#if defined(SYZ_EXECUTOR) || defined(SYZ_TUN_ENABLE) static void vsnprintf_check(char* str, size_t size, const char* format, va_list args) { int rv; @@ -348,9 +348,9 @@ void debug_dump_data(const char* data, int length) if (i % 16 != 0) debug("\n"); } -#endif // SYZ_TUN_ENABLE +#endif -#if (defined(__NR_syz_emit_ethernet) && defined(SYZ_TUN_ENABLE)) || defined(__NR_syz_test) +#if defined(SYZ_EXECUTOR) || (defined(__NR_syz_emit_ethernet) && defined(SYZ_TUN_ENABLE)) || defined(__NR_syz_test) struct csum_inet { uint32_t acc; }; @@ -382,7 +382,7 @@ uint16_t csum_inet_digest(struct csum_inet* csum) } #endif -#if defined(__NR_syz_emit_ethernet) && defined(SYZ_TUN_ENABLE) +#if defined(SYZ_EXECUTOR) || (defined(__NR_syz_emit_ethernet) && defined(SYZ_TUN_ENABLE)) static uintptr_t syz_emit_ethernet(uintptr_t a0, uintptr_t a1) { // syz_emit_ethernet(len len[packet], packet ptr[in, eth_packet]) @@ -397,7 +397,7 @@ static uintptr_t syz_emit_ethernet(uintptr_t a0, uintptr_t a1) } #endif -#if (defined(SYZ_EXECUTOR) || defined(SYZ_REPEAT)) && defined(SYZ_TUN_ENABLE) +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_TUN_ENABLE)) void flush_tun() { char data[SYZ_TUN_MAX_PACKET_SIZE]; @@ -406,7 +406,7 @@ void flush_tun() } #endif -#if defined(__NR_syz_extract_tcp_res) && defined(SYZ_TUN_ENABLE) +#if defined(SYZ_EXECUTOR) || (defined(__NR_syz_extract_tcp_res) && defined(SYZ_TUN_ENABLE)) // Can't include , since it causes // conflicts due to some structs redefinition. struct ipv6hdr { @@ -618,20 +618,20 @@ static uintptr_t execute_syscall(int nr, uintptr_t a0, uintptr_t a1, uintptr_t a #endif #if defined(__NR_syz_emit_ethernet) case __NR_syz_emit_ethernet: -#if defined(SYZ_TUN_ENABLE) +#if defined(SYZ_EXECUTOR) || defined(SYZ_TUN_ENABLE) return syz_emit_ethernet(a0, a1); #else return 0; -#endif // defined(SYZ_TUN_ENABLE) -#endif // defined(__NR_syz_emit_ethernet) +#endif +#endif #if defined(__NR_syz_extract_tcp_res) case __NR_syz_extract_tcp_res: -#if defined(SYZ_TUN_ENABLE) +#if defined(SYZ_EXECUTOR) || defined(SYZ_TUN_ENABLE) return syz_extract_tcp_res(a0, a1, a2); #else return 0; -#endif // defined(SYZ_TUN_ENABLE) -#endif // defined(__NR_syz_extract_tcp_res) +#endif +#endif #ifdef __NR_syz_kvm_setup_cpu case __NR_syz_kvm_setup_cpu: return syz_kvm_setup_cpu(a0, a1, a2, a3, a4, a5, a6, a7); @@ -671,7 +671,7 @@ static int do_sandbox_none(int executor_pid, bool enable_tun) return pid; sandbox_common(); -#ifdef SYZ_TUN_ENABLE +#if defined(SYZ_EXECUTOR) || defined(SYZ_TUN_ENABLE) setup_tun(executor_pid, enable_tun); #endif @@ -688,7 +688,7 @@ static int do_sandbox_setuid(int executor_pid, bool enable_tun) return pid; sandbox_common(); -#ifdef SYZ_TUN_ENABLE +#if defined(SYZ_EXECUTOR) || defined(SYZ_TUN_ENABLE) setup_tun(executor_pid, enable_tun); #endif @@ -751,7 +751,7 @@ static int namespace_sandbox_proc(void* arg) if (!write_file("/proc/self/gid_map", "0 %d 1\n", real_gid)) fail("write of /proc/self/gid_map failed"); -#ifdef SYZ_TUN_ENABLE +#if defined(SYZ_EXECUTOR) || defined(SYZ_TUN_ENABLE) // For sandbox namespace we setup tun after initializing uid mapping, // otherwise ip commands fail. setup_tun(epid, etun); @@ -946,7 +946,7 @@ void loop() setpgrp(); if (chdir(cwdbuf)) fail("failed to chdir"); -#if defined(SYZ_TUN_ENABLE) +#ifdef SYZ_TUN_ENABLE flush_tun(); #endif test(); diff --git a/executor/executor.cc b/executor/executor.cc index 04624cdc8..e0280054c 100644 --- a/executor/executor.cc +++ b/executor/executor.cc @@ -31,7 +31,6 @@ #include "syscalls.h" #define SYZ_EXECUTOR -#define SYZ_TUN_ENABLE #include "common.h" #define KCOV_INIT_TRACE _IOR('c', 1, unsigned long long) -- cgit mrf-deployment 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 +++++++++++--------- executor/common.h | 29 ++++++++++++++++++++--------- executor/common_kvm_amd64.h | 9 +++++++++ repro/repro.go | 28 ++++++++++++++++++++-------- tools/syz-prog2c/prog2c.go | 44 +++++++++++++++++++++++--------------------- 7 files changed, 134 insertions(+), 69 deletions(-) (limited to 'executor/common.h') 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) } } } diff --git a/executor/common.h b/executor/common.h index 5041aaf7b..032365471 100644 --- a/executor/common.h +++ b/executor/common.h @@ -132,6 +132,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; @@ -175,6 +176,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() { @@ -189,15 +200,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)) @@ -469,8 +471,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); @@ -492,7 +499,11 @@ static uintptr_t syz_open_dev(uintptr_t a0, uintptr_t a1, uintptr_t a2) // syz_open_dev(dev strconst, id intptr, flags flags[open_flags]) fd 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); // 10 devices should be enough for everyone. diff --git a/executor/common_kvm_amd64.h b/executor/common_kvm_amd64.h index dd37733ed..e4753223e 100644 --- a/executor/common_kvm_amd64.h +++ b/executor/common_kvm_amd64.h @@ -7,6 +7,15 @@ // See Intel Software Developer’s Manual Volume 3: System Programming Guide // for details on what happens here. +// We could put each NONFAILING use in this file under ifdef, +// but I don't think it's worth it. +#ifndef NONFAILING +#define NONFAILING(x) \ + { \ + x; \ + } +#endif + #include "kvm.S.h" #include "kvm.h" diff --git a/repro/repro.go b/repro/repro.go index 3ae553bac..f4cfde322 100644 --- a/repro/repro.go +++ b/repro/repro.go @@ -151,14 +151,15 @@ func (ctx *context) repro(entries []*prog.LogEntry, crashStart int) (*Result, er } Logf(2, "reproducing crash '%v': suspecting %v programs", ctx.crashDesc, len(suspected)) opts := csource.Options{ - Threaded: true, - Collide: true, - Repeat: true, - Procs: ctx.cfg.Procs, - Sandbox: ctx.cfg.Sandbox, - EnableTun: true, - UseTmpDir: true, - Repro: true, + Threaded: true, + Collide: true, + Repeat: true, + Procs: ctx.cfg.Procs, + Sandbox: ctx.cfg.Sandbox, + EnableTun: true, + UseTmpDir: true, + HandleSegv: true, + Repro: true, } // Execute the suspected programs. // We first try to execute each program for 10 seconds, that should detect simple crashes @@ -299,6 +300,17 @@ func (ctx *context) repro(entries []*prog.LogEntry, crashStart int) (*Result, er res.Opts = opts } } + if res.Opts.HandleSegv { + opts = res.Opts + opts.HandleSegv = false + crashed, err := ctx.testCProg(res.Prog, duration, opts) + if err != nil { + return res, err + } + if crashed { + res.Opts = opts + } + } return res, nil } diff --git a/tools/syz-prog2c/prog2c.go b/tools/syz-prog2c/prog2c.go index 878772d42..1d2007755 100644 --- a/tools/syz-prog2c/prog2c.go +++ b/tools/syz-prog2c/prog2c.go @@ -14,16 +14,17 @@ import ( ) var ( - flagThreaded = flag.Bool("threaded", false, "create threaded program") - flagCollide = flag.Bool("collide", false, "create collide program") - flagRepeat = flag.Bool("repeat", false, "repeat program infinitely or not") - flagProcs = flag.Int("procs", 4, "number of parallel processes") - flagSandbox = flag.String("sandbox", "none", "sandbox to use (none, setuid, namespace)") - flagProg = flag.String("prog", "", "file with program to convert (required)") - flagFaultCall = flag.Int("fault_call", -1, "inject fault into this call (0-based)") - flagFaultNth = flag.Int("fault_nth", 0, "inject fault on n-th operation (0-based)") - flagEnableTun = flag.Bool("tun", false, "set up TUN/TAP interface") - flagUseTmpDir = flag.Bool("tmpdir", false, "create a temporary dir and execute inside it") + flagThreaded = flag.Bool("threaded", false, "create threaded program") + flagCollide = flag.Bool("collide", false, "create collide program") + flagRepeat = flag.Bool("repeat", false, "repeat program infinitely or not") + flagProcs = flag.Int("procs", 4, "number of parallel processes") + flagSandbox = flag.String("sandbox", "none", "sandbox to use (none, setuid, namespace)") + flagProg = flag.String("prog", "", "file with program to convert (required)") + flagFaultCall = flag.Int("fault_call", -1, "inject fault into this call (0-based)") + flagFaultNth = flag.Int("fault_nth", 0, "inject fault on n-th operation (0-based)") + flagEnableTun = flag.Bool("tun", false, "set up TUN/TAP interface") + flagUseTmpDir = flag.Bool("tmpdir", false, "create a temporary dir and execute inside it") + flagHandleSegv = flag.Bool("segv", false, "catch and ignore SIGSEGV") ) func main() { @@ -43,17 +44,18 @@ func main() { os.Exit(1) } opts := csource.Options{ - Threaded: *flagThreaded, - Collide: *flagCollide, - Repeat: *flagRepeat, - Procs: *flagProcs, - Sandbox: *flagSandbox, - Fault: *flagFaultCall >= 0, - FaultCall: *flagFaultCall, - FaultNth: *flagFaultNth, - EnableTun: *flagEnableTun, - UseTmpDir: *flagUseTmpDir, - Repro: false, + Threaded: *flagThreaded, + Collide: *flagCollide, + Repeat: *flagRepeat, + Procs: *flagProcs, + Sandbox: *flagSandbox, + Fault: *flagFaultCall >= 0, + FaultCall: *flagFaultCall, + FaultNth: *flagFaultNth, + EnableTun: *flagEnableTun, + UseTmpDir: *flagUseTmpDir, + HandleSegv: *flagHandleSegv, + Repro: false, } src, err := csource.Write(p, opts) if err != nil { -- cgit mrf-deployment From 4d1df73af9a6d40d3111e3f2a7dfb9f138fbde4b Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Thu, 18 May 2017 16:08:43 +0200 Subject: csource: force enable tun flag when required --- csource/common.go | 12 ++---------- csource/csource.go | 16 ++++++++++++++++ executor/common.h | 12 ++---------- prog/analysis.go | 26 ++++++++++++++++++++++++++ repro/repro.go | 2 +- 5 files changed, 47 insertions(+), 21 deletions(-) (limited to 'executor/common.h') diff --git a/csource/common.go b/csource/common.go index 8d4a74146..c0abd4412 100644 --- a/csource/common.go +++ b/csource/common.go @@ -1536,21 +1536,13 @@ static uintptr_t execute_syscall(int nr, uintptr_t a0, uintptr_t a1, uintptr_t a case __NR_syz_fuseblk_mount: return syz_fuseblk_mount(a0, a1, a2, a3, a4, a5, a6, a7); #endif -#if defined(__NR_syz_emit_ethernet) +#ifdef __NR_syz_emit_ethernet case __NR_syz_emit_ethernet: -#if defined(SYZ_EXECUTOR) || defined(SYZ_TUN_ENABLE) return syz_emit_ethernet(a0, a1); -#else - return 0; -#endif #endif -#if defined(__NR_syz_extract_tcp_res) +#ifdef __NR_syz_extract_tcp_res case __NR_syz_extract_tcp_res: -#if defined(SYZ_EXECUTOR) || defined(SYZ_TUN_ENABLE) return syz_extract_tcp_res(a0, a1, a2); -#else - return 0; -#endif #endif #ifdef __NR_syz_kvm_setup_cpu case __NR_syz_kvm_setup_cpu: diff --git a/csource/csource.go b/csource/csource.go index ccc235f7e..0a5bcddd7 100644 --- a/csource/csource.go +++ b/csource/csource.go @@ -42,6 +42,18 @@ type Options struct { Repro bool } +func RequiresTun(p *prog.Prog) bool { + for _, c := range p.Calls { + switch c.Meta.CallName { + case "syz_emit_ethernet": + return true + case "syz_extract_tcp_seq": + return true + } + } + return false +} + func Write(p *prog.Prog, opts Options) ([]byte, error) { exec := make([]byte, prog.ExecBufferSize) if err := p.SerializeForExec(exec, 0); err != nil { @@ -49,6 +61,10 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) { } w := new(bytes.Buffer) + if RequiresTun(p) { + opts.EnableTun = true + } + fmt.Fprint(w, "// autogenerated by syzkaller (http://github.com/google/syzkaller)\n\n") handled := make(map[string]int) diff --git a/executor/common.h b/executor/common.h index 032365471..934f98cf5 100644 --- a/executor/common.h +++ b/executor/common.h @@ -627,21 +627,13 @@ static uintptr_t execute_syscall(int nr, uintptr_t a0, uintptr_t a1, uintptr_t a case __NR_syz_fuseblk_mount: return syz_fuseblk_mount(a0, a1, a2, a3, a4, a5, a6, a7); #endif -#if defined(__NR_syz_emit_ethernet) +#ifdef __NR_syz_emit_ethernet case __NR_syz_emit_ethernet: -#if defined(SYZ_EXECUTOR) || defined(SYZ_TUN_ENABLE) return syz_emit_ethernet(a0, a1); -#else - return 0; -#endif #endif -#if defined(__NR_syz_extract_tcp_res) +#ifdef __NR_syz_extract_tcp_res case __NR_syz_extract_tcp_res: -#if defined(SYZ_EXECUTOR) || defined(SYZ_TUN_ENABLE) return syz_extract_tcp_res(a0, a1, a2); -#else - return 0; -#endif #endif #ifdef __NR_syz_kvm_setup_cpu case __NR_syz_kvm_setup_cpu: diff --git a/prog/analysis.go b/prog/analysis.go index 5b786c753..67a254273 100644 --- a/prog/analysis.go +++ b/prog/analysis.go @@ -260,3 +260,29 @@ func sanitizeCall(c *Call) { } } } + +func RequiresTun(p *Prog) bool { + for _, c := range p.Calls { + switch c.Meta.CallName { + case "syz_emit_ethernet": + return true + case "syz_extract_tcp_res": + return true + } + } + return false +} + +func RequiresBitmasks(p *Prog) bool { + result := false + for _, c := range p.Calls { + foreachArg(c, func(arg, _ *Arg, _ *[]*Arg) { + if arg.Kind == ArgConst { + if arg.Type.BitfieldOffset() != 0 || arg.Type.BitfieldLength() != 0 { + result = true + } + } + }) + } + return result +} diff --git a/repro/repro.go b/repro/repro.go index f4cfde322..741387af9 100644 --- a/repro/repro.go +++ b/repro/repro.go @@ -278,7 +278,7 @@ func (ctx *context) repro(entries []*prog.LogEntry, crashStart int) (*Result, er } // Try to simplify the C reproducer. - if res.Opts.EnableTun { + if res.Opts.EnableTun && !csource.RequiresTun(res.Prog) { opts = res.Opts opts.EnableTun = false crashed, err := ctx.testCProg(res.Prog, duration, opts) -- cgit mrf-deployment From 1bdb387c18a852e75aef0b3c4ddb0481f90d66bd Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Thu, 18 May 2017 16:38:10 +0200 Subject: csource: emit bitmasks only when required --- csource/common.go | 35 ++++++++++++++++++++--------------- csource/csource.go | 21 ++++++--------------- executor/common.h | 30 ++++++++++++++++-------------- repro/repro.go | 2 +- 4 files changed, 43 insertions(+), 45 deletions(-) (limited to 'executor/common.h') diff --git a/csource/common.go b/csource/common.go index c0abd4412..3ac10334d 100644 --- a/csource/common.go +++ b/csource/common.go @@ -116,6 +116,22 @@ void debug(const char* msg, ...) fflush(stdout); } +#if defined(SYZ_EXECUTOR) || defined(SYZ_USE_BITMASKS) +#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)) + +#define STORE_BY_BITMASK(type, addr, val, bf_off, bf_len) \ + if ((bf_off) == 0 && (bf_len) == 0) { \ + *(type*)(addr) = (type)(val); \ + } else { \ + type new_val = *(type*)(addr); \ + new_val &= ~BITMASK_LEN_OFF(type, (bf_off), (bf_len)); \ + new_val |= ((type)(val)&BITMASK_LEN(type, (bf_len))) << (bf_off); \ + *(type*)(addr) = new_val; \ + } +#endif + #if defined(SYZ_EXECUTOR) || defined(SYZ_HANDLE_SEGV) __thread int skip_segv; __thread jmp_buf segv_env; @@ -175,20 +191,6 @@ static void use_temporary_dir() } #endif -#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)) - -#define STORE_BY_BITMASK(type, addr, val, bf_off, bf_len) \ - if ((bf_off) == 0 && (bf_len) == 0) { \ - *(type*)(addr) = (type)(val); \ - } else { \ - type new_val = *(type*)(addr); \ - new_val &= ~BITMASK_LEN_OFF(type, (bf_off), (bf_len)); \ - new_val |= ((type)(val)&BITMASK_LEN(type, (bf_len))) << (bf_off); \ - *(type*)(addr) = new_val; \ - } - #if defined(SYZ_EXECUTOR) || defined(SYZ_TUN_ENABLE) static void vsnprintf_check(char* str, size_t size, const char* format, va_list args) { @@ -551,7 +553,10 @@ static uintptr_t syz_fuseblk_mount(uintptr_t a0, uintptr_t a1, uintptr_t a2, uin #ifndef NONFAILING -#define NONFAILING(x) { x; } +#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"; diff --git a/csource/csource.go b/csource/csource.go index 0a5bcddd7..8faae8e5e 100644 --- a/csource/csource.go +++ b/csource/csource.go @@ -42,18 +42,6 @@ type Options struct { Repro bool } -func RequiresTun(p *prog.Prog) bool { - for _, c := range p.Calls { - switch c.Meta.CallName { - case "syz_emit_ethernet": - return true - case "syz_extract_tcp_seq": - return true - } - } - return false -} - func Write(p *prog.Prog, opts Options) ([]byte, error) { exec := make([]byte, prog.ExecBufferSize) if err := p.SerializeForExec(exec, 0); err != nil { @@ -61,7 +49,7 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) { } w := new(bytes.Buffer) - if RequiresTun(p) { + if prog.RequiresTun(p) { opts.EnableTun = true } @@ -78,7 +66,7 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) { } fmt.Fprintf(w, "\n") - hdr, err := preprocessCommonHeader(opts, handled) + hdr, err := preprocessCommonHeader(opts, handled, prog.RequiresBitmasks(p)) if err != nil { return nil, err } @@ -340,8 +328,11 @@ loop: return calls, n } -func preprocessCommonHeader(opts Options, handled map[string]int) (string, error) { +func preprocessCommonHeader(opts Options, handled map[string]int, useBitmasks bool) (string, error) { var defines []string + if useBitmasks { + defines = append(defines, "SYZ_USE_BITMASKS") + } switch opts.Sandbox { case "none": defines = append(defines, "SYZ_SANDBOX_NONE") diff --git a/executor/common.h b/executor/common.h index 934f98cf5..609bab1c8 100644 --- a/executor/common.h +++ b/executor/common.h @@ -132,6 +132,22 @@ void debug(const char* msg, ...) fflush(stdout); } +#if defined(SYZ_EXECUTOR) || defined(SYZ_USE_BITMASKS) +#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)) + +#define STORE_BY_BITMASK(type, addr, val, bf_off, bf_len) \ + if ((bf_off) == 0 && (bf_len) == 0) { \ + *(type*)(addr) = (type)(val); \ + } else { \ + type new_val = *(type*)(addr); \ + new_val &= ~BITMASK_LEN_OFF(type, (bf_off), (bf_len)); \ + new_val |= ((type)(val)&BITMASK_LEN(type, (bf_len))) << (bf_off); \ + *(type*)(addr) = new_val; \ + } +#endif + #if defined(SYZ_EXECUTOR) || defined(SYZ_HANDLE_SEGV) __thread int skip_segv; __thread jmp_buf segv_env; @@ -200,20 +216,6 @@ static void use_temporary_dir() } #endif -#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)) - -#define STORE_BY_BITMASK(type, addr, val, bf_off, bf_len) \ - if ((bf_off) == 0 && (bf_len) == 0) { \ - *(type*)(addr) = (type)(val); \ - } else { \ - type new_val = *(type*)(addr); \ - new_val &= ~BITMASK_LEN_OFF(type, (bf_off), (bf_len)); \ - new_val |= ((type)(val)&BITMASK_LEN(type, (bf_len))) << (bf_off); \ - *(type*)(addr) = new_val; \ - } - #if defined(SYZ_EXECUTOR) || defined(SYZ_TUN_ENABLE) static void vsnprintf_check(char* str, size_t size, const char* format, va_list args) { diff --git a/repro/repro.go b/repro/repro.go index 741387af9..e6ab35cc3 100644 --- a/repro/repro.go +++ b/repro/repro.go @@ -278,7 +278,7 @@ func (ctx *context) repro(entries []*prog.LogEntry, crashStart int) (*Result, er } // Try to simplify the C reproducer. - if res.Opts.EnableTun && !csource.RequiresTun(res.Prog) { + if res.Opts.EnableTun && !prog.RequiresTun(res.Prog) { opts = res.Opts opts.EnableTun = false crashed, err := ctx.testCProg(res.Prog, duration, opts) -- cgit mrf-deployment From 73a895df6168bc12559d1fa16aae7e52646d7ec3 Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Thu, 18 May 2017 17:03:02 +0200 Subject: csource: use sandbox only when required --- csource/common.go | 2 ++ csource/csource.go | 41 ++++++++++++++++++++++++++++++++--------- csource/csource_test.go | 2 +- executor/common.h | 2 ++ repro/repro.go | 11 +++++++++++ tools/syz-prog2c/prog2c.go | 2 +- 6 files changed, 49 insertions(+), 11 deletions(-) (limited to 'executor/common.h') diff --git a/csource/common.go b/csource/common.go index 3ac10334d..74f4aba35 100644 --- a/csource/common.go +++ b/csource/common.go @@ -1556,6 +1556,7 @@ static uintptr_t execute_syscall(int nr, uintptr_t a0, uintptr_t a1, uintptr_t a } } +#if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NONE) || defined(SYZ_SANDBOX_SETUID) || defined(SYZ_SANDBOX_NAMESPACE) static void loop(); static void sandbox_common() @@ -1578,6 +1579,7 @@ static void sandbox_common() unshare(CLONE_NEWIPC); unshare(CLONE_IO); } +#endif #if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NONE) static int do_sandbox_none(int executor_pid, bool enable_tun) diff --git a/csource/csource.go b/csource/csource.go index 8faae8e5e..603cb37f5 100644 --- a/csource/csource.go +++ b/csource/csource.go @@ -86,9 +86,16 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) { if opts.UseTmpDir { fmt.Fprintf(w, "\tuse_temporary_dir();\n") } - fmt.Fprintf(w, "\tint pid = do_sandbox_%v(0, %v);\n", opts.Sandbox, opts.EnableTun) - fmt.Fprint(w, "\tint status = 0;\n") - fmt.Fprint(w, "\twhile (waitpid(pid, &status, __WALL) != pid) {}\n") + if opts.Sandbox != "" { + fmt.Fprintf(w, "\tint pid = do_sandbox_%v(0, %v);\n", opts.Sandbox, opts.EnableTun) + fmt.Fprint(w, "\tint status = 0;\n") + fmt.Fprint(w, "\twhile (waitpid(pid, &status, __WALL) != pid) {}\n") + } else { + if opts.EnableTun { + fmt.Fprintf(w, "\tsetup_tun(0, %v);\n", opts.EnableTun) + } + fmt.Fprint(w, "\tloop();\n") + } fmt.Fprint(w, "\treturn 0;\n}\n") } else { generateTestFunc(w, opts, calls, "test") @@ -100,9 +107,16 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) { if opts.UseTmpDir { fmt.Fprintf(w, "\tuse_temporary_dir();\n") } - fmt.Fprintf(w, "\tint pid = do_sandbox_%v(0, %v);\n", opts.Sandbox, opts.EnableTun) - fmt.Fprint(w, "\tint status = 0;\n") - fmt.Fprint(w, "\twhile (waitpid(pid, &status, __WALL) != pid) {}\n") + if opts.Sandbox != "" { + fmt.Fprintf(w, "\tint pid = do_sandbox_%v(0, %v);\n", opts.Sandbox, opts.EnableTun) + fmt.Fprint(w, "\tint status = 0;\n") + fmt.Fprint(w, "\twhile (waitpid(pid, &status, __WALL) != pid) {}\n") + } else { + if opts.EnableTun { + fmt.Fprintf(w, "\tsetup_tun(0, %v);\n", opts.EnableTun) + } + fmt.Fprint(w, "\tloop();\n") + } fmt.Fprint(w, "\treturn 0;\n}\n") } else { fmt.Fprint(w, "int main()\n{\n") @@ -115,9 +129,16 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) { if opts.UseTmpDir { fmt.Fprintf(w, "\t\t\tuse_temporary_dir();\n") } - fmt.Fprintf(w, "\t\t\tint pid = do_sandbox_%v(i, %v);\n", opts.Sandbox, opts.EnableTun) - fmt.Fprint(w, "\t\t\tint status = 0;\n") - fmt.Fprint(w, "\t\t\twhile (waitpid(pid, &status, __WALL) != pid) {}\n") + if opts.Sandbox != "" { + fmt.Fprintf(w, "\t\t\tint pid = do_sandbox_%v(i, %v);\n", opts.Sandbox, opts.EnableTun) + fmt.Fprint(w, "\t\t\tint status = 0;\n") + fmt.Fprint(w, "\t\t\twhile (waitpid(pid, &status, __WALL) != pid) {}\n") + } else { + if opts.EnableTun { + fmt.Fprintf(w, "\t\t\tsetup_tun(i, %v);\n", opts.EnableTun) + } + fmt.Fprint(w, "\t\t\tloop();\n") + } fmt.Fprint(w, "\t\t\treturn 0;\n") fmt.Fprint(w, "\t\t}\n") fmt.Fprint(w, "\t}\n") @@ -334,6 +355,8 @@ func preprocessCommonHeader(opts Options, handled map[string]int, useBitmasks bo defines = append(defines, "SYZ_USE_BITMASKS") } switch opts.Sandbox { + case "": + // No sandbox, do nothing. case "none": defines = append(defines, "SYZ_SANDBOX_NONE") case "setuid": diff --git a/csource/csource_test.go b/csource/csource_test.go index dbecec54c..ca39b162a 100644 --- a/csource/csource_test.go +++ b/csource/csource_test.go @@ -33,7 +33,7 @@ func allOptionsPermutations() []Options { for _, opt.Collide = range []bool{false, true} { for _, opt.Repeat = range []bool{false, true} { for _, opt.Procs = range []int{1, 4} { - for _, opt.Sandbox = range []string{"none", "setuid", "namespace"} { + for _, opt.Sandbox = range []string{"", "none", "setuid", "namespace"} { for _, opt.Repro = range []bool{false, true} { for _, opt.Fault = range []bool{false, true} { for _, opt.EnableTun = range []bool{false, true} { diff --git a/executor/common.h b/executor/common.h index 609bab1c8..4ee1cd140 100644 --- a/executor/common.h +++ b/executor/common.h @@ -644,6 +644,7 @@ static uintptr_t execute_syscall(int nr, uintptr_t a0, uintptr_t a1, uintptr_t a } } +#if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NONE) || defined(SYZ_SANDBOX_SETUID) || defined(SYZ_SANDBOX_NAMESPACE) static void loop(); static void sandbox_common() @@ -667,6 +668,7 @@ static void sandbox_common() unshare(CLONE_NEWIPC); unshare(CLONE_IO); } +#endif #if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NONE) static int do_sandbox_none(int executor_pid, bool enable_tun) diff --git a/repro/repro.go b/repro/repro.go index e6ab35cc3..d6d46eff3 100644 --- a/repro/repro.go +++ b/repro/repro.go @@ -289,6 +289,17 @@ func (ctx *context) repro(entries []*prog.LogEntry, crashStart int) (*Result, er res.Opts = opts } } + if res.Opts.Sandbox != "" { + opts = res.Opts + opts.Sandbox = "" + crashed, err := ctx.testCProg(res.Prog, duration, opts) + if err != nil { + return res, err + } + if crashed { + res.Opts = opts + } + } if res.Opts.UseTmpDir { opts = res.Opts opts.UseTmpDir = false diff --git a/tools/syz-prog2c/prog2c.go b/tools/syz-prog2c/prog2c.go index 1d2007755..75a5126e3 100644 --- a/tools/syz-prog2c/prog2c.go +++ b/tools/syz-prog2c/prog2c.go @@ -18,7 +18,7 @@ var ( flagCollide = flag.Bool("collide", false, "create collide program") flagRepeat = flag.Bool("repeat", false, "repeat program infinitely or not") flagProcs = flag.Int("procs", 4, "number of parallel processes") - flagSandbox = flag.String("sandbox", "none", "sandbox to use (none, setuid, namespace)") + flagSandbox = flag.String("sandbox", "", "sandbox to use (none, setuid, namespace)") flagProg = flag.String("prog", "", "file with program to convert (required)") flagFaultCall = flag.Int("fault_call", -1, "inject fault into this call (0-based)") flagFaultNth = flag.Int("fault_nth", 0, "inject fault on n-th operation (0-based)") -- cgit mrf-deployment From c99b02d2248fbdcd6f44037326b16c928f4423f1 Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Thu, 18 May 2017 18:17:16 +0200 Subject: csource: try to simplify repeat loop --- csource/common.go | 13 ++++++++++--- csource/csource.go | 4 ++++ csource/csource_test.go | 23 ++++++++++++++--------- executor/common.h | 13 ++++++++++--- repro/repro.go | 12 ++++++++++++ tools/syz-prog2c/prog2c.go | 2 ++ 6 files changed, 52 insertions(+), 15 deletions(-) (limited to 'executor/common.h') diff --git a/csource/common.go b/csource/common.go index 74f4aba35..b4d3f0a33 100644 --- a/csource/common.go +++ b/csource/common.go @@ -1728,7 +1728,7 @@ static int do_sandbox_namespace(int executor_pid, bool enable_tun) } #endif -#if defined(SYZ_EXECUTOR) || defined(SYZ_REPEAT) +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) static void remove_dir(const char* dir) { DIR* dp; @@ -1797,9 +1797,7 @@ retry: exitf("rmdir(%s) failed", dir); } } -#endif -#if defined(SYZ_EXECUTOR) || defined(SYZ_REPEAT) static uint64_t current_time_ms() { struct timespec ts; @@ -1830,6 +1828,7 @@ static int inject_fault(int nth) #if defined(SYZ_REPEAT) static void test(); +#if defined(SYZ_WAIT_REPEAT) void loop() { int iter; @@ -1870,5 +1869,13 @@ void loop() remove_dir(cwdbuf); } } +#else +void loop() +{ + while (1) { + test(); + } +} +#endif #endif ` diff --git a/csource/csource.go b/csource/csource.go index 603cb37f5..ae3e54df8 100644 --- a/csource/csource.go +++ b/csource/csource.go @@ -36,6 +36,7 @@ type Options struct { EnableTun bool UseTmpDir bool HandleSegv bool + WaitRepeat bool // Generate code for use with repro package to prints log messages, // which allows to distinguish between a hang and an absent crash. @@ -381,6 +382,9 @@ func preprocessCommonHeader(opts Options, handled map[string]int, useBitmasks bo if opts.HandleSegv { defines = append(defines, "SYZ_HANDLE_SEGV") } + if opts.WaitRepeat { + defines = append(defines, "SYZ_WAIT_REPEAT") + } for name, _ := range handled { defines = append(defines, "__NR_"+name) } diff --git a/csource/csource_test.go b/csource/csource_test.go index ca39b162a..097e014ec 100644 --- a/csource/csource_test.go +++ b/csource/csource_test.go @@ -39,16 +39,21 @@ func allOptionsPermutations() []Options { for _, opt.EnableTun = range []bool{false, true} { for _, opt.UseTmpDir = range []bool{false, true} { for _, opt.HandleSegv = range []bool{false, true} { - if opt.Collide && !opt.Threaded { - continue + for _, opt.WaitRepeat = range []bool{false, true} { + if opt.Collide && !opt.Threaded { + continue + } + if !opt.Repeat && opt.Procs != 1 { + continue + } + if !opt.Repeat && opt.WaitRepeat { + 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) } } } diff --git a/executor/common.h b/executor/common.h index 4ee1cd140..6e4955fab 100644 --- a/executor/common.h +++ b/executor/common.h @@ -827,7 +827,7 @@ static int do_sandbox_namespace(int executor_pid, bool enable_tun) } #endif -#if defined(SYZ_EXECUTOR) || defined(SYZ_REPEAT) +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) // One does not simply remove a directory. // There can be mounts, so we need to try to umount. // Moreover, a mount can be mounted several times, so we need to try to umount in a loop. @@ -904,9 +904,7 @@ retry: exitf("rmdir(%s) failed", dir); } } -#endif -#if defined(SYZ_EXECUTOR) || defined(SYZ_REPEAT) static uint64_t current_time_ms() { struct timespec ts; @@ -937,6 +935,7 @@ static int inject_fault(int nth) #if defined(SYZ_REPEAT) static void test(); +#if defined(SYZ_WAIT_REPEAT) void loop() { int iter; @@ -977,4 +976,12 @@ void loop() remove_dir(cwdbuf); } } +#else +void loop() +{ + while (1) { + test(); + } +} +#endif #endif diff --git a/repro/repro.go b/repro/repro.go index d6d46eff3..23d59856d 100644 --- a/repro/repro.go +++ b/repro/repro.go @@ -159,6 +159,7 @@ func (ctx *context) repro(entries []*prog.LogEntry, crashStart int) (*Result, er EnableTun: true, UseTmpDir: true, HandleSegv: true, + WaitRepeat: true, Repro: true, } // Execute the suspected programs. @@ -322,6 +323,17 @@ func (ctx *context) repro(entries []*prog.LogEntry, crashStart int) (*Result, er res.Opts = opts } } + if res.Opts.WaitRepeat { + opts = res.Opts + opts.WaitRepeat = false + crashed, err := ctx.testCProg(res.Prog, duration, opts) + if err != nil { + return res, err + } + if crashed { + res.Opts = opts + } + } return res, nil } diff --git a/tools/syz-prog2c/prog2c.go b/tools/syz-prog2c/prog2c.go index 75a5126e3..4eadb6377 100644 --- a/tools/syz-prog2c/prog2c.go +++ b/tools/syz-prog2c/prog2c.go @@ -25,6 +25,7 @@ var ( flagEnableTun = flag.Bool("tun", false, "set up TUN/TAP interface") flagUseTmpDir = flag.Bool("tmpdir", false, "create a temporary dir and execute inside it") flagHandleSegv = flag.Bool("segv", false, "catch and ignore SIGSEGV") + flagWaitRepeat = flag.Bool("waitrepeat", false, "wait for each repeat attempt") ) func main() { @@ -55,6 +56,7 @@ func main() { EnableTun: *flagEnableTun, UseTmpDir: *flagUseTmpDir, HandleSegv: *flagHandleSegv, + WaitRepeat: *flagWaitRepeat, Repro: false, } src, err := csource.Write(p, opts) -- cgit mrf-deployment From 120e26c2fecf4fcabc18af43329171d6afba02b4 Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Thu, 18 May 2017 19:18:26 +0200 Subject: csourse: don't generate debug printfs --- csource/common.go | 34 ++++++++++++++++++++++++++++++++-- csource/csource.go | 4 ++++ csource/csource_test.go | 26 ++++++++++++++------------ executor/common.h | 34 ++++++++++++++++++++++++++++++++-- repro/repro.go | 12 ++++++++++++ tools/syz-prog2c/prog2c.go | 2 ++ 6 files changed, 96 insertions(+), 16 deletions(-) (limited to 'executor/common.h') diff --git a/csource/common.go b/csource/common.go index b4d3f0a33..d4d6890f0 100644 --- a/csource/common.go +++ b/csource/common.go @@ -103,6 +103,7 @@ __attribute__((noreturn)) void exitf(const char* msg, ...) doexit(kRetryStatus); } +#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) static int flag_debug; void debug(const char* msg, ...) @@ -115,6 +116,7 @@ void debug(const char* msg, ...) va_end(args); fflush(stdout); } +#endif #if defined(SYZ_EXECUTOR) || defined(SYZ_USE_BITMASKS) #define BITMASK_LEN(type, bf_len) (type)((1ull << (bf_len)) - 1) @@ -142,10 +144,14 @@ static void segv_handler(int sig, siginfo_t* info, void* uctx) const uintptr_t prog_start = 1 << 20; const uintptr_t prog_end = 100 << 20; if (__atomic_load_n(&skip_segv, __ATOMIC_RELAXED) && (addr < prog_start || addr > prog_end)) { +#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("SIGSEGV on %p, skipping\n", addr); +#endif _longjmp(segv_env, 1); } +#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("SIGSEGV on %p, exiting\n", addr); +#endif doexit(sig); for (;;) { } @@ -298,8 +304,10 @@ static void setup_tun(uint64_t pid, bool enable_tun) if (enable_tun) initialize_tun(pid); } +#endif -int read_tun(char* data, int size) +#if defined(SYZ_EXECUTOR) || (defined(SYZ_TUN_ENABLE) && (defined(__NR_syz_extract_tcp_res) || defined(SYZ_REPEAT))) +static int read_tun(char* data, int size) { int rv = read(tunfd, data, size); if (rv < 0) { @@ -309,8 +317,10 @@ int read_tun(char* data, int size) } return rv; } +#endif -void debug_dump_data(const char* data, int length) +#if defined(SYZ_EXECUTOR) || (defined(SYZ_DEBUG) && defined(SYZ_TUN_ENABLE) && (defined(__NR_syz_emit_ethernet) || defined(__NR_syz_extract_tcp_res))) +static void debug_dump_data(const char* data, int length) { int i; for (i = 0; i < length; i++) { @@ -364,7 +374,9 @@ static uintptr_t syz_emit_ethernet(uintptr_t a0, uintptr_t a1) int64_t length = a0; char* data = (char*)a1; +#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug_dump_data(data, length); +#endif return write(tunfd, data, length); } #endif @@ -408,7 +420,9 @@ static uintptr_t syz_extract_tcp_res(uintptr_t a0, uintptr_t a1, uintptr_t a2) if (rv == -1) return (uintptr_t)-1; size_t length = rv; +#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug_dump_data(data, length); +#endif struct tcphdr* tcphdr; @@ -445,8 +459,10 @@ static uintptr_t syz_extract_tcp_res(uintptr_t a0, uintptr_t a1, uintptr_t a2) res->ack = htonl((ntohl(tcphdr->ack_seq) + (uint32_t)a2)); #endif +#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("extracted seq: %08x\n", res->seq); debug("extracted ack: %08x\n", res->ack); +#endif return 0; } @@ -1686,7 +1702,9 @@ static int namespace_sandbox_proc(void* arg) if (mkdir("./syz-tmp/pivot", 0777)) fail("mkdir failed"); if (syscall(SYS_pivot_root, "./syz-tmp", "./syz-tmp/pivot")) { +#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("pivot_root failed"); +#endif if (chdir("./syz-tmp")) fail("chdir failed"); } else { @@ -1756,16 +1774,22 @@ retry: } int i; for (i = 0;; i++) { +#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("unlink(%s)\n", filename); +#endif if (unlink(filename) == 0) break; if (errno == EROFS) { +#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("ignoring EROFS\n"); +#endif break; } if (errno != EBUSY || i > 100) exitf("unlink(%s) failed", filename); +#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("umount(%s)\n", filename); +#endif if (umount2(filename, MNT_DETACH)) exitf("umount(%s) failed", filename); } @@ -1773,16 +1797,22 @@ retry: closedir(dp); int i; for (i = 0;; i++) { +#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("rmdir(%s)\n", dir); +#endif if (rmdir(dir) == 0) break; if (i < 100) { if (errno == EROFS) { +#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("ignoring EROFS\n"); +#endif break; } if (errno == EBUSY) { +#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("umount(%s)\n", dir); +#endif if (umount2(dir, MNT_DETACH)) exitf("umount(%s) failed", dir); continue; diff --git a/csource/csource.go b/csource/csource.go index ae3e54df8..3eeb369dc 100644 --- a/csource/csource.go +++ b/csource/csource.go @@ -37,6 +37,7 @@ type Options struct { UseTmpDir bool HandleSegv bool WaitRepeat bool + Debug bool // Generate code for use with repro package to prints log messages, // which allows to distinguish between a hang and an absent crash. @@ -385,6 +386,9 @@ func preprocessCommonHeader(opts Options, handled map[string]int, useBitmasks bo if opts.WaitRepeat { defines = append(defines, "SYZ_WAIT_REPEAT") } + if opts.Debug { + defines = append(defines, "SYZ_DEBUG") + } for name, _ := range handled { defines = append(defines, "__NR_"+name) } diff --git a/csource/csource_test.go b/csource/csource_test.go index 097e014ec..7b68954f3 100644 --- a/csource/csource_test.go +++ b/csource/csource_test.go @@ -40,19 +40,21 @@ func allOptionsPermutations() []Options { for _, opt.UseTmpDir = range []bool{false, true} { for _, opt.HandleSegv = range []bool{false, true} { for _, opt.WaitRepeat = range []bool{false, true} { - if opt.Collide && !opt.Threaded { - continue + for _, opt.Debug = range []bool{false, true} { + if opt.Collide && !opt.Threaded { + continue + } + if !opt.Repeat && opt.Procs != 1 { + continue + } + if !opt.Repeat && opt.WaitRepeat { + continue + } + if testing.Short() && opt.Procs != 1 { + continue + } + options = append(options, opt) } - if !opt.Repeat && opt.Procs != 1 { - continue - } - if !opt.Repeat && opt.WaitRepeat { - continue - } - if testing.Short() && opt.Procs != 1 { - continue - } - options = append(options, opt) } } } diff --git a/executor/common.h b/executor/common.h index 6e4955fab..57ff0d95b 100644 --- a/executor/common.h +++ b/executor/common.h @@ -119,6 +119,7 @@ __attribute__((noreturn)) void exitf(const char* msg, ...) doexit(kRetryStatus); } +#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) static int flag_debug; void debug(const char* msg, ...) @@ -131,6 +132,7 @@ void debug(const char* msg, ...) va_end(args); fflush(stdout); } +#endif #if defined(SYZ_EXECUTOR) || defined(SYZ_USE_BITMASKS) #define BITMASK_LEN(type, bf_len) (type)((1ull << (bf_len)) - 1) @@ -164,10 +166,14 @@ static void segv_handler(int sig, siginfo_t* info, void* uctx) const uintptr_t prog_start = 1 << 20; const uintptr_t prog_end = 100 << 20; if (__atomic_load_n(&skip_segv, __ATOMIC_RELAXED) && (addr < prog_start || addr > prog_end)) { +#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("SIGSEGV on %p, skipping\n", addr); +#endif _longjmp(segv_env, 1); } +#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("SIGSEGV on %p, exiting\n", addr); +#endif doexit(sig); for (;;) { } @@ -329,8 +335,10 @@ static void setup_tun(uint64_t pid, bool enable_tun) if (enable_tun) initialize_tun(pid); } +#endif -int read_tun(char* data, int size) +#if defined(SYZ_EXECUTOR) || (defined(SYZ_TUN_ENABLE) && (defined(__NR_syz_extract_tcp_res) || defined(SYZ_REPEAT))) +static int read_tun(char* data, int size) { int rv = read(tunfd, data, size); if (rv < 0) { @@ -340,8 +348,10 @@ int read_tun(char* data, int size) } return rv; } +#endif -void debug_dump_data(const char* data, int length) +#if defined(SYZ_EXECUTOR) || (defined(SYZ_DEBUG) && defined(SYZ_TUN_ENABLE) && (defined(__NR_syz_emit_ethernet) || defined(__NR_syz_extract_tcp_res))) +static void debug_dump_data(const char* data, int length) { int i; for (i = 0; i < length; i++) { @@ -396,7 +406,9 @@ static uintptr_t syz_emit_ethernet(uintptr_t a0, uintptr_t a1) int64_t length = a0; char* data = (char*)a1; +#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug_dump_data(data, length); +#endif return write(tunfd, data, length); } #endif @@ -443,7 +455,9 @@ static uintptr_t syz_extract_tcp_res(uintptr_t a0, uintptr_t a1, uintptr_t a2) if (rv == -1) return (uintptr_t)-1; size_t length = rv; +#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug_dump_data(data, length); +#endif struct tcphdr* tcphdr; @@ -481,8 +495,10 @@ static uintptr_t syz_extract_tcp_res(uintptr_t a0, uintptr_t a1, uintptr_t a2) res->ack = htonl((ntohl(tcphdr->ack_seq) + (uint32_t)a2)); #endif +#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("extracted seq: %08x\n", res->seq); debug("extracted ack: %08x\n", res->ack); +#endif return 0; } @@ -781,7 +797,9 @@ static int namespace_sandbox_proc(void* arg) if (mkdir("./syz-tmp/pivot", 0777)) fail("mkdir failed"); if (syscall(SYS_pivot_root, "./syz-tmp", "./syz-tmp/pivot")) { +#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("pivot_root failed"); +#endif if (chdir("./syz-tmp")) fail("chdir failed"); } else { @@ -863,16 +881,22 @@ retry: } int i; for (i = 0;; i++) { +#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("unlink(%s)\n", filename); +#endif if (unlink(filename) == 0) break; if (errno == EROFS) { +#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("ignoring EROFS\n"); +#endif break; } if (errno != EBUSY || i > 100) exitf("unlink(%s) failed", filename); +#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("umount(%s)\n", filename); +#endif if (umount2(filename, MNT_DETACH)) exitf("umount(%s) failed", filename); } @@ -880,16 +904,22 @@ retry: closedir(dp); int i; for (i = 0;; i++) { +#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("rmdir(%s)\n", dir); +#endif if (rmdir(dir) == 0) break; if (i < 100) { if (errno == EROFS) { +#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("ignoring EROFS\n"); +#endif break; } if (errno == EBUSY) { +#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("umount(%s)\n", dir); +#endif if (umount2(dir, MNT_DETACH)) exitf("umount(%s) failed", dir); continue; diff --git a/repro/repro.go b/repro/repro.go index 23d59856d..4101da1ae 100644 --- a/repro/repro.go +++ b/repro/repro.go @@ -160,6 +160,7 @@ func (ctx *context) repro(entries []*prog.LogEntry, crashStart int) (*Result, er UseTmpDir: true, HandleSegv: true, WaitRepeat: true, + Debug: true, Repro: true, } // Execute the suspected programs. @@ -334,6 +335,17 @@ func (ctx *context) repro(entries []*prog.LogEntry, crashStart int) (*Result, er res.Opts = opts } } + if res.Opts.Debug { + opts = res.Opts + opts.Debug = false + crashed, err := ctx.testCProg(res.Prog, duration, opts) + if err != nil { + return res, err + } + if crashed { + res.Opts = opts + } + } return res, nil } diff --git a/tools/syz-prog2c/prog2c.go b/tools/syz-prog2c/prog2c.go index 4eadb6377..e3089c3ce 100644 --- a/tools/syz-prog2c/prog2c.go +++ b/tools/syz-prog2c/prog2c.go @@ -26,6 +26,7 @@ var ( flagUseTmpDir = flag.Bool("tmpdir", false, "create a temporary dir and execute inside it") flagHandleSegv = flag.Bool("segv", false, "catch and ignore SIGSEGV") flagWaitRepeat = flag.Bool("waitrepeat", false, "wait for each repeat attempt") + flagDebug = flag.Bool("debug", false, "generate debug printfs") ) func main() { @@ -57,6 +58,7 @@ func main() { UseTmpDir: *flagUseTmpDir, HandleSegv: *flagHandleSegv, WaitRepeat: *flagWaitRepeat, + Debug: *flagDebug, Repro: false, } src, err := csource.Write(p, opts) -- cgit mrf-deployment From 19015af81522aa5d8aaa16d07306c48c3a61571e Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Thu, 18 May 2017 19:41:20 +0200 Subject: csource: only emit fail(), exitf() and doexit() when necessary --- csource/common.go | 16 +++++++++++++++- executor/common.h | 16 +++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) (limited to 'executor/common.h') diff --git a/csource/common.go b/csource/common.go index d4d6890f0..466e6de43 100644 --- a/csource/common.go +++ b/csource/common.go @@ -49,10 +49,18 @@ var commonHeader = ` #include #include +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || defined(SYZ_USE_TMP_DIR) || \ + defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || defined(SYZ_SANDBOX_SETUID) || defined(__NR_syz_kvm_setup_cpu) const int kFailStatus = 67; -const int kErrorStatus = 68; const int kRetryStatus = 69; +#endif + +#if defined(SYZ_EXECUTOR) +const int kErrorStatus = 68; +#endif +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || defined(SYZ_USE_TMP_DIR) || defined(SYZ_HANDLE_SEGV) || \ + defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || defined(SYZ_SANDBOX_SETUID) || defined(SYZ_SANDBOX_NONE) || defined(__NR_syz_kvm_setup_cpu) __attribute__((noreturn)) void doexit(int status) { volatile unsigned i; @@ -60,12 +68,15 @@ __attribute__((noreturn)) void doexit(int status) for (i = 0;; i++) { } } +#endif #if defined(SYZ_EXECUTOR) #define exit use_doexit_instead #define _exit use_doexit_instead #endif +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || defined(SYZ_USE_TMP_DIR) || \ + defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || defined(SYZ_SANDBOX_SETUID) || defined(__NR_syz_kvm_setup_cpu) __attribute__((noreturn)) void fail(const char* msg, ...) { int e = errno; @@ -77,6 +88,7 @@ __attribute__((noreturn)) void fail(const char* msg, ...) fprintf(stderr, " (errno %d)\n", e); doexit((e == ENOMEM || e == EAGAIN) ? kRetryStatus : kFailStatus); } +#endif #if defined(SYZ_EXECUTOR) __attribute__((noreturn)) void error(const char* msg, ...) @@ -91,6 +103,7 @@ __attribute__((noreturn)) void error(const char* msg, ...) } #endif +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) __attribute__((noreturn)) void exitf(const char* msg, ...) { int e = errno; @@ -102,6 +115,7 @@ __attribute__((noreturn)) void exitf(const char* msg, ...) fprintf(stderr, " (errno %d)\n", e); doexit(kRetryStatus); } +#endif #if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) static int flag_debug; diff --git a/executor/common.h b/executor/common.h index 57ff0d95b..ef2778f64 100644 --- a/executor/common.h +++ b/executor/common.h @@ -48,10 +48,18 @@ #include #include +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || defined(SYZ_USE_TMP_DIR) || \ + defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || defined(SYZ_SANDBOX_SETUID) || defined(__NR_syz_kvm_setup_cpu) const int kFailStatus = 67; -const int kErrorStatus = 68; const int kRetryStatus = 69; +#endif + +#if defined(SYZ_EXECUTOR) +const int kErrorStatus = 68; +#endif +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || defined(SYZ_USE_TMP_DIR) || defined(SYZ_HANDLE_SEGV) || \ + defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || defined(SYZ_SANDBOX_SETUID) || defined(SYZ_SANDBOX_NONE) || defined(__NR_syz_kvm_setup_cpu) // One does not simply exit. // _exit can in fact fail. // syzkaller did manage to generate a seccomp filter that prohibits exit_group syscall. @@ -70,6 +78,7 @@ __attribute__((noreturn)) void doexit(int status) for (i = 0;; i++) { } } +#endif #if defined(SYZ_EXECUTOR) // exit/_exit do not necessary work. @@ -77,6 +86,8 @@ __attribute__((noreturn)) void doexit(int status) #define _exit use_doexit_instead #endif +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || defined(SYZ_USE_TMP_DIR) || \ + defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || defined(SYZ_SANDBOX_SETUID) || defined(__NR_syz_kvm_setup_cpu) // logical error (e.g. invalid input program), use as an assert() alernative __attribute__((noreturn)) void fail(const char* msg, ...) { @@ -91,6 +102,7 @@ __attribute__((noreturn)) void fail(const char* msg, ...) // so handle it here as non-fatal error. doexit((e == ENOMEM || e == EAGAIN) ? kRetryStatus : kFailStatus); } +#endif #if defined(SYZ_EXECUTOR) // kernel error (e.g. wrong syscall return value) @@ -106,6 +118,7 @@ __attribute__((noreturn)) void error(const char* msg, ...) } #endif +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) // just exit (e.g. due to temporal ENOMEM error) __attribute__((noreturn)) void exitf(const char* msg, ...) { @@ -118,6 +131,7 @@ __attribute__((noreturn)) void exitf(const char* msg, ...) fprintf(stderr, " (errno %d)\n", e); doexit(kRetryStatus); } +#endif #if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) static int flag_debug; -- cgit mrf-deployment From ed6891f2edb833a3ba06dc656bb8cfe371d0bc6a Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Thu, 18 May 2017 20:24:41 +0200 Subject: csource: use tmp dir in repeat loop when tmpdir flag is on --- csource/common.go | 10 +++++++++- executor/common.h | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) (limited to 'executor/common.h') diff --git a/csource/common.go b/csource/common.go index 466e6de43..0d78bca5f 100644 --- a/csource/common.go +++ b/csource/common.go @@ -1760,7 +1760,7 @@ static int do_sandbox_namespace(int executor_pid, bool enable_tun) } #endif -#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT) && defined(SYZ_USE_TMP_DIR)) static void remove_dir(const char* dir) { DIR* dp; @@ -1841,7 +1841,9 @@ retry: exitf("rmdir(%s) failed", dir); } } +#endif +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) static uint64_t current_time_ms() { struct timespec ts; @@ -1877,18 +1879,22 @@ void loop() { int iter; for (iter = 0;; iter++) { +#ifdef SYZ_USE_TMP_DIR char cwdbuf[256]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) fail("failed to mkdir"); +#endif int pid = fork(); if (pid < 0) fail("clone failed"); if (pid == 0) { prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); setpgrp(); +#ifdef SYZ_USE_TMP_DIR if (chdir(cwdbuf)) fail("failed to chdir"); +#endif #ifdef SYZ_TUN_ENABLE flush_tun(); #endif @@ -1910,7 +1916,9 @@ void loop() break; } } +#ifdef SYZ_USE_TMP_DIR remove_dir(cwdbuf); +#endif } } #else diff --git a/executor/common.h b/executor/common.h index ef2778f64..7f0bfb7f5 100644 --- a/executor/common.h +++ b/executor/common.h @@ -859,7 +859,7 @@ static int do_sandbox_namespace(int executor_pid, bool enable_tun) } #endif -#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT) && defined(SYZ_USE_TMP_DIR)) // One does not simply remove a directory. // There can be mounts, so we need to try to umount. // Moreover, a mount can be mounted several times, so we need to try to umount in a loop. @@ -948,7 +948,9 @@ retry: exitf("rmdir(%s) failed", dir); } } +#endif +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) static uint64_t current_time_ms() { struct timespec ts; @@ -984,18 +986,22 @@ void loop() { int iter; for (iter = 0;; iter++) { +#ifdef SYZ_USE_TMP_DIR char cwdbuf[256]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) fail("failed to mkdir"); +#endif int pid = fork(); if (pid < 0) fail("clone failed"); if (pid == 0) { prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); setpgrp(); +#ifdef SYZ_USE_TMP_DIR if (chdir(cwdbuf)) fail("failed to chdir"); +#endif #ifdef SYZ_TUN_ENABLE flush_tun(); #endif @@ -1017,7 +1023,9 @@ void loop() break; } } +#ifdef SYZ_USE_TMP_DIR remove_dir(cwdbuf); +#endif } } #else -- cgit mrf-deployment From ab9fabf95864c5183713081c05a3780060e0940f Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Fri, 19 May 2017 15:53:19 +0200 Subject: csource: don't generate execute_syscall calls --- csource/common.go | 2 ++ csource/csource.go | 30 ++++++++++++++++++++++++------ executor/common.h | 2 ++ sys/decl.go | 1 + sysgen/sysgen.go | 6 +++++- 5 files changed, 34 insertions(+), 7 deletions(-) (limited to 'executor/common.h') diff --git a/csource/common.go b/csource/common.go index 0d78bca5f..ce75156ae 100644 --- a/csource/common.go +++ b/csource/common.go @@ -1546,6 +1546,7 @@ static uintptr_t syz_kvm_setup_cpu(uintptr_t a0, uintptr_t a1, uintptr_t a2, uin #endif #endif +#ifdef SYZ_EXECUTOR static uintptr_t execute_syscall(int nr, uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8) { switch (nr) { @@ -1585,6 +1586,7 @@ static uintptr_t execute_syscall(int nr, uintptr_t a0, uintptr_t a1, uintptr_t a #endif } } +#endif #if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NONE) || defined(SYZ_SANDBOX_SETUID) || defined(SYZ_SANDBOX_NAMESPACE) static void loop(); diff --git a/csource/csource.go b/csource/csource.go index 3eeb369dc..4e51a3ee5 100644 --- a/csource/csource.go +++ b/csource/csource.go @@ -321,28 +321,46 @@ loop: 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) + emitCall := true + if meta.CallName == "syz_test" { + emitCall = false + } + if emitCall { + if meta.Native { + fmt.Fprintf(w, "\tr[%v] = syscall(__NR_%v", n, meta.CallName) + } else { + fmt.Fprintf(w, "\tr[%v] = %v(", n, meta.CallName) + } + } nargs := read() for i := uintptr(0); i < nargs; i++ { typ := read() size := read() _ = size + if emitCall && (meta.Native || i > 0) { + fmt.Fprintf(w, ", ") + } switch typ { case prog.ExecArgConst: - fmt.Fprintf(w, ", 0x%xul", read()) + value := read() + if emitCall { + fmt.Fprintf(w, "0x%xul", value) + } // Bitfields can't be args of a normal syscall, so just ignore them. read() // bit field offset read() // bit field length case prog.ExecArgResult: - fmt.Fprintf(w, ", %v", resultRef()) + ref := resultRef() + if emitCall { + fmt.Fprintf(w, "%v", ref) + } default: panic(fmt.Sprintf("unknown arg type %v", typ)) } } - for i := nargs; i < 9; i++ { - fmt.Fprintf(w, ", 0") + if emitCall { + fmt.Fprintf(w, ");\n") } - fmt.Fprintf(w, ");\n") lastCall = n seenCall = true } diff --git a/executor/common.h b/executor/common.h index 7f0bfb7f5..f1df1148b 100644 --- a/executor/common.h +++ b/executor/common.h @@ -634,6 +634,7 @@ static uintptr_t syz_kvm_setup_cpu(uintptr_t a0, uintptr_t a1, uintptr_t a2, uin #endif #endif // #ifdef __NR_syz_kvm_setup_cpu +#ifdef SYZ_EXECUTOR static uintptr_t execute_syscall(int nr, uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8) { switch (nr) { @@ -673,6 +674,7 @@ static uintptr_t execute_syscall(int nr, uintptr_t a0, uintptr_t a1, uintptr_t a #endif } } +#endif #if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NONE) || defined(SYZ_SANDBOX_SETUID) || defined(SYZ_SANDBOX_NAMESPACE) static void loop(); diff --git a/sys/decl.go b/sys/decl.go index 05eadedec..03d51a1c4 100644 --- a/sys/decl.go +++ b/sys/decl.go @@ -14,6 +14,7 @@ type Call struct { NR int // kernel syscall number Name string CallName string + Native bool // real of fake syscall Args []Type Ret Type } diff --git a/sysgen/sysgen.go b/sysgen/sysgen.go index 7454ae60c..b30a04437 100644 --- a/sysgen/sysgen.go +++ b/sysgen/sysgen.go @@ -177,7 +177,11 @@ func generate(arch string, desc *Description, consts map[string]uint64, out io.W logf(0, "unsupported syscall: %v", s.CallName) } } - fmt.Fprintf(out, "&Call{Name: \"%v\", CallName: \"%v\"", s.Name, s.CallName) + native := true + if _, ok := syzkalls[s.CallName]; ok { + native = false + } + fmt.Fprintf(out, "&Call{Name: \"%v\", CallName: \"%v\", Native: %v", s.Name, s.CallName, native) if len(s.Ret) != 0 { fmt.Fprintf(out, ", Ret: ") generateArg("", "ret", s.Ret[0], "out", s.Ret[1:], desc, consts, true, false, out) -- cgit mrf-deployment From fce462fb99651fe1e4f92fce28c8218ac7daf976 Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Mon, 29 May 2017 15:15:39 +0200 Subject: csource: generate includes when necessary --- csource/common.go | 127 ++++++++++++++++++++++++++++++++++++++++++----------- csource/csource.go | 10 ++++- executor/common.h | 127 ++++++++++++++++++++++++++++++++++++++++++----------- 3 files changed, 213 insertions(+), 51 deletions(-) (limited to 'executor/common.h') diff --git a/csource/common.go b/csource/common.go index ce75156ae..2d26c2c4e 100644 --- a/csource/common.go +++ b/csource/common.go @@ -8,49 +8,123 @@ var commonHeader = ` #define _GNU_SOURCE #endif -#include -#include +#include +#include +#include +#include +#if defined(SYZ_EXECUTOR) || defined(SYZ_THREADED) || defined(SYZ_COLLIDE) +#include +#endif +#if defined(SYZ_EXECUTOR) || defined(SYZ_COLLIDE) +#include +#endif +#if defined(SYZ_EXECUTOR) || defined(SYZ_HANDLE_SEGV) +#include +#include +#include +#endif +#if defined(SYZ_EXECUTOR) || defined(SYZ_USE_TMP_DIR) +#include +#include +#include +#include +#include +#endif +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) +#include +#include +#include +#include +#include +#include +#include +#include +#endif +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT) && defined(SYZ_USE_TMP_DIR)) +#include #include +#endif +#if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NONE) || defined(SYZ_SANDBOX_SETUID) || defined(SYZ_SANDBOX_NAMESPACE) +#include +#include +#include +#include +#include +#include #include #include -#include -#include -#include #include -#include #include - +#endif +#if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_SETUID) +#include +#endif +#if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NAMESPACE) +#include #include -#include -#include - +#include +#include +#include +#endif +#if defined(SYZ_EXECUTOR) || defined(SYZ_TUN_ENABLE) #include +#include +#include #include #include #include #include #include #include - -#include -#include +#include +#include +#include +#include +#include +#include +#endif +#if defined(SYZ_EXECUTOR) || defined(SYZ_FAULT_INJECTION) #include #include -#include -#include -#include -#include #include #include +#include +#include +#endif +#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) +#include +#include +#endif +#ifdef __NR_syz_open_dev +#include +#include +#include +#endif +#if defined(__NR_syz_fuse_mount) || defined(__NR_syz_fuseblk_mount) +#include +#include +#include +#endif +#ifdef __NR_syz_open_pts +#include +#include +#include +#include +#endif +#ifdef __NR_syz_kvm_setup_cpu +#include +#include +#include +#include #include -#include #include -#include -#include -#include +#include +#include +#endif #if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || defined(SYZ_USE_TMP_DIR) || \ - defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || defined(SYZ_SANDBOX_SETUID) || defined(__NR_syz_kvm_setup_cpu) + defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || defined(SYZ_SANDBOX_SETUID) || \ + defined(SYZ_FAULT_INJECTION) || defined(__NR_syz_kvm_setup_cpu) const int kFailStatus = 67; const int kRetryStatus = 69; #endif @@ -59,8 +133,10 @@ const int kRetryStatus = 69; const int kErrorStatus = 68; #endif -#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || defined(SYZ_USE_TMP_DIR) || defined(SYZ_HANDLE_SEGV) || \ - defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || defined(SYZ_SANDBOX_SETUID) || defined(SYZ_SANDBOX_NONE) || defined(__NR_syz_kvm_setup_cpu) +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || defined(SYZ_USE_TMP_DIR) || \ + defined(SYZ_HANDLE_SEGV) || defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || \ + defined(SYZ_SANDBOX_SETUID) || defined(SYZ_SANDBOX_NONE) || defined(SYZ_FAULT_INJECTION) || \ + defined(__NR_syz_kvm_setup_cpu) __attribute__((noreturn)) void doexit(int status) { volatile unsigned i; @@ -76,7 +152,8 @@ __attribute__((noreturn)) void doexit(int status) #endif #if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || defined(SYZ_USE_TMP_DIR) || \ - defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || defined(SYZ_SANDBOX_SETUID) || defined(__NR_syz_kvm_setup_cpu) + defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || defined(SYZ_SANDBOX_SETUID) || \ + defined(SYZ_FAULT_INJECTION) || defined(__NR_syz_kvm_setup_cpu) __attribute__((noreturn)) void fail(const char* msg, ...) { int e = errno; diff --git a/csource/csource.go b/csource/csource.go index 4e51a3ee5..8231a97ac 100644 --- a/csource/csource.go +++ b/csource/csource.go @@ -190,7 +190,9 @@ func generateTestFunc(w io.Writer, opts Options, calls []string, name string) { fmt.Fprintf(w, "\tsyscall(SYS_write, 1, \"executing program\\n\", strlen(\"executing program\\n\"));\n") } fmt.Fprintf(w, "\tmemset(r, -1, sizeof(r));\n") - fmt.Fprintf(w, "\tsrand(getpid());\n") + if opts.Collide { + fmt.Fprintf(w, "\tsrand(getpid());\n") + } fmt.Fprintf(w, "\tfor (i = 0; i < %v; i++) {\n", len(calls)) fmt.Fprintf(w, "\t\tpthread_create(&th[i], 0, thr, (void*)i);\n") fmt.Fprintf(w, "\t\tusleep(10000);\n") @@ -386,6 +388,12 @@ func preprocessCommonHeader(opts Options, handled map[string]int, useBitmasks bo default: return "", fmt.Errorf("unknown sandbox mode: %v", opts.Sandbox) } + if opts.Threaded { + defines = append(defines, "SYZ_THREADED") + } + if opts.Collide { + defines = append(defines, "SYZ_COLLIDE") + } if opts.Repeat { defines = append(defines, "SYZ_REPEAT") } diff --git a/executor/common.h b/executor/common.h index f1df1148b..00b9ba723 100644 --- a/executor/common.h +++ b/executor/common.h @@ -7,49 +7,123 @@ #define _GNU_SOURCE #endif -#include -#include +#include +#include +#include +#include +#if defined(SYZ_EXECUTOR) || defined(SYZ_THREADED) || defined(SYZ_COLLIDE) +#include +#endif +#if defined(SYZ_EXECUTOR) || defined(SYZ_COLLIDE) +#include +#endif +#if defined(SYZ_EXECUTOR) || defined(SYZ_HANDLE_SEGV) +#include +#include +#include +#endif +#if defined(SYZ_EXECUTOR) || defined(SYZ_USE_TMP_DIR) +#include +#include +#include +#include +#include +#endif +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) +#include +#include +#include +#include +#include +#include +#include +#include +#endif +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT) && defined(SYZ_USE_TMP_DIR)) +#include #include +#endif +#if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NONE) || defined(SYZ_SANDBOX_SETUID) || defined(SYZ_SANDBOX_NAMESPACE) +#include +#include +#include +#include +#include +#include #include #include -#include -#include -#include #include -#include #include - +#endif +#if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_SETUID) +#include +#endif +#if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NAMESPACE) +#include #include -#include -#include - +#include +#include +#include +#endif +#if defined(SYZ_EXECUTOR) || defined(SYZ_TUN_ENABLE) #include +#include +#include #include #include #include #include #include #include - -#include -#include +#include +#include +#include +#include +#include +#include +#endif +#if defined(SYZ_EXECUTOR) || defined(SYZ_FAULT_INJECTION) #include #include -#include -#include -#include -#include #include #include +#include +#include +#endif +#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) +#include +#include +#endif +#ifdef __NR_syz_open_dev +#include +#include +#include +#endif +#if defined(__NR_syz_fuse_mount) || defined(__NR_syz_fuseblk_mount) +#include +#include +#include +#endif +#ifdef __NR_syz_open_pts +#include +#include +#include +#include +#endif +#ifdef __NR_syz_kvm_setup_cpu +#include +#include +#include +#include #include -#include #include -#include -#include -#include +#include +#include +#endif #if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || defined(SYZ_USE_TMP_DIR) || \ - defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || defined(SYZ_SANDBOX_SETUID) || defined(__NR_syz_kvm_setup_cpu) + defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || defined(SYZ_SANDBOX_SETUID) || \ + defined(SYZ_FAULT_INJECTION) || defined(__NR_syz_kvm_setup_cpu) const int kFailStatus = 67; const int kRetryStatus = 69; #endif @@ -58,8 +132,10 @@ const int kRetryStatus = 69; const int kErrorStatus = 68; #endif -#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || defined(SYZ_USE_TMP_DIR) || defined(SYZ_HANDLE_SEGV) || \ - defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || defined(SYZ_SANDBOX_SETUID) || defined(SYZ_SANDBOX_NONE) || defined(__NR_syz_kvm_setup_cpu) +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || defined(SYZ_USE_TMP_DIR) || \ + defined(SYZ_HANDLE_SEGV) || defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || \ + defined(SYZ_SANDBOX_SETUID) || defined(SYZ_SANDBOX_NONE) || defined(SYZ_FAULT_INJECTION) || \ + defined(__NR_syz_kvm_setup_cpu) // One does not simply exit. // _exit can in fact fail. // syzkaller did manage to generate a seccomp filter that prohibits exit_group syscall. @@ -87,7 +163,8 @@ __attribute__((noreturn)) void doexit(int status) #endif #if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || defined(SYZ_USE_TMP_DIR) || \ - defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || defined(SYZ_SANDBOX_SETUID) || defined(__NR_syz_kvm_setup_cpu) + defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || defined(SYZ_SANDBOX_SETUID) || \ + defined(SYZ_FAULT_INJECTION) || defined(__NR_syz_kvm_setup_cpu) // logical error (e.g. invalid input program), use as an assert() alernative __attribute__((noreturn)) void fail(const char* msg, ...) { -- cgit mrf-deployment From b3ea23c379f1d883266e545f18a5f83562cf8f1c Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Mon, 29 May 2017 18:22:55 +0200 Subject: repro: always minimize over EnableTun --- csource/common.go | 2 +- csource/csource.go | 14 ++++++++------ executor/common.h | 2 +- prog/analysis.go | 24 ++++++++++++------------ repro/repro.go | 2 +- 5 files changed, 23 insertions(+), 21 deletions(-) (limited to 'executor/common.h') diff --git a/csource/common.go b/csource/common.go index 2d26c2c4e..4db577579 100644 --- a/csource/common.go +++ b/csource/common.go @@ -424,7 +424,7 @@ static void debug_dump_data(const char* data, int length) } #endif -#if defined(SYZ_EXECUTOR) || (defined(__NR_syz_emit_ethernet) && defined(SYZ_TUN_ENABLE)) || defined(__NR_syz_test) +#if defined(SYZ_EXECUTOR) || defined(SYZ_USE_CHECKSUMS) || defined(__NR_syz_test) struct csum_inet { uint32_t acc; }; diff --git a/csource/csource.go b/csource/csource.go index 8231a97ac..45a52dcf7 100644 --- a/csource/csource.go +++ b/csource/csource.go @@ -51,10 +51,6 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) { } w := new(bytes.Buffer) - if prog.RequiresTun(p) { - opts.EnableTun = true - } - fmt.Fprint(w, "// autogenerated by syzkaller (http://github.com/google/syzkaller)\n\n") handled := make(map[string]int) @@ -68,7 +64,7 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) { } fmt.Fprintf(w, "\n") - hdr, err := preprocessCommonHeader(opts, handled, prog.RequiresBitmasks(p)) + hdr, err := preprocessCommonHeader(opts, handled, prog.RequiresBitmasks(p), prog.RequiresChecksums(p)) if err != nil { return nil, err } @@ -327,6 +323,9 @@ loop: if meta.CallName == "syz_test" { emitCall = false } + if !opts.EnableTun && (meta.CallName == "syz_emit_ethernet" || meta.CallName == "syz_extract_tcp_res") { + emitCall = false + } if emitCall { if meta.Native { fmt.Fprintf(w, "\tr[%v] = syscall(__NR_%v", n, meta.CallName) @@ -371,11 +370,14 @@ loop: return calls, n } -func preprocessCommonHeader(opts Options, handled map[string]int, useBitmasks bool) (string, error) { +func preprocessCommonHeader(opts Options, handled map[string]int, useBitmasks, useChecksums bool) (string, error) { var defines []string if useBitmasks { defines = append(defines, "SYZ_USE_BITMASKS") } + if useBitmasks { + defines = append(defines, "SYZ_USE_CHECKSUMS") + } switch opts.Sandbox { case "": // No sandbox, do nothing. diff --git a/executor/common.h b/executor/common.h index 00b9ba723..1be840bc4 100644 --- a/executor/common.h +++ b/executor/common.h @@ -455,7 +455,7 @@ static void debug_dump_data(const char* data, int length) } #endif -#if defined(SYZ_EXECUTOR) || (defined(__NR_syz_emit_ethernet) && defined(SYZ_TUN_ENABLE)) || defined(__NR_syz_test) +#if defined(SYZ_EXECUTOR) || defined(SYZ_USE_CHECKSUMS) || defined(__NR_syz_test) struct csum_inet { uint32_t acc; }; diff --git a/prog/analysis.go b/prog/analysis.go index 67a254273..df9a0599d 100644 --- a/prog/analysis.go +++ b/prog/analysis.go @@ -261,18 +261,6 @@ func sanitizeCall(c *Call) { } } -func RequiresTun(p *Prog) bool { - for _, c := range p.Calls { - switch c.Meta.CallName { - case "syz_emit_ethernet": - return true - case "syz_extract_tcp_res": - return true - } - } - return false -} - func RequiresBitmasks(p *Prog) bool { result := false for _, c := range p.Calls { @@ -286,3 +274,15 @@ func RequiresBitmasks(p *Prog) bool { } return result } + +func RequiresChecksums(p *Prog) bool { + result := false + for _, c := range p.Calls { + foreachArg(c, func(arg, _ *Arg, _ *[]*Arg) { + if _, ok := arg.Type.(*sys.CsumType); ok { + result = true + } + }) + } + return result +} diff --git a/repro/repro.go b/repro/repro.go index 4101da1ae..345942526 100644 --- a/repro/repro.go +++ b/repro/repro.go @@ -280,7 +280,7 @@ func (ctx *context) repro(entries []*prog.LogEntry, crashStart int) (*Result, er } // Try to simplify the C reproducer. - if res.Opts.EnableTun && !prog.RequiresTun(res.Prog) { + if res.Opts.EnableTun { opts = res.Opts opts.EnableTun = false crashed, err := ctx.testCProg(res.Prog, duration, opts) -- cgit mrf-deployment From e2d5e973c12c393b5cb50c3fa9252146c2cb0447 Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Tue, 6 Jun 2017 13:52:57 +0200 Subject: csource: don't use guard macros for debug() and NONFAILING() --- csource/common.go | 176 +++++++++++++++++--------------------------- csource/csource.go | 44 +++++++---- executor/common.h | 33 --------- executor/common_kvm_amd64.h | 145 +++++++++++++++++------------------- 4 files changed, 166 insertions(+), 232 deletions(-) (limited to 'executor/common.h') diff --git a/csource/common.go b/csource/common.go index 4db577579..8c63b637e 100644 --- a/csource/common.go +++ b/csource/common.go @@ -235,14 +235,10 @@ static void segv_handler(int sig, siginfo_t* info, void* uctx) const uintptr_t prog_start = 1 << 20; const uintptr_t prog_end = 100 << 20; if (__atomic_load_n(&skip_segv, __ATOMIC_RELAXED) && (addr < prog_start || addr > prog_end)) { -#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("SIGSEGV on %p, skipping\n", addr); -#endif _longjmp(segv_env, 1); } -#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("SIGSEGV on %p, exiting\n", addr); -#endif doexit(sig); for (;;) { } @@ -465,9 +461,7 @@ static uintptr_t syz_emit_ethernet(uintptr_t a0, uintptr_t a1) int64_t length = a0; char* data = (char*)a1; -#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug_dump_data(data, length); -#endif return write(tunfd, data, length); } #endif @@ -511,9 +505,7 @@ static uintptr_t syz_extract_tcp_res(uintptr_t a0, uintptr_t a1, uintptr_t a2) if (rv == -1) return (uintptr_t)-1; size_t length = rv; -#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug_dump_data(data, length); -#endif struct tcphdr* tcphdr; @@ -542,18 +534,11 @@ 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 -#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("extracted seq: %08x\n", res->seq); debug("extracted ack: %08x\n", res->ack); -#endif return 0; } @@ -569,11 +554,7 @@ 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); @@ -659,13 +640,6 @@ 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"; @@ -1352,69 +1326,71 @@ static uintptr_t syz_kvm_setup_cpu(uintptr_t a0, uintptr_t a1, uintptr_t a2, uin } } - struct tss16* tss16 = (struct tss16*)(host_mem + seg_tss16_2.base); - NONFAILING( - struct tss16* tss = tss16; - memset(tss, 0, sizeof(*tss)); - tss->ss0 = tss->ss1 = tss->ss2 = SEL_DS16; - tss->sp0 = tss->sp1 = tss->sp2 = ADDR_STACK0; - tss->ip = ADDR_VAR_USER_CODE2; - tss->flags = (1 << 1); - tss->cs = SEL_CS16; - tss->es = tss->ds = tss->ss = SEL_DS16; - tss->ldt = SEL_LDT); - struct tss16* tss16_cpl3 = (struct tss16*)(host_mem + seg_tss16_cpl3.base); - NONFAILING( - struct tss16* tss = tss16_cpl3; - memset(tss, 0, sizeof(*tss)); - tss->ss0 = tss->ss1 = tss->ss2 = SEL_DS16; - tss->sp0 = tss->sp1 = tss->sp2 = ADDR_STACK0; - tss->ip = ADDR_VAR_USER_CODE2; - tss->flags = (1 << 1); - tss->cs = SEL_CS16_CPL3; - tss->es = tss->ds = tss->ss = SEL_DS16_CPL3; - tss->ldt = SEL_LDT); - struct tss32* tss32 = (struct tss32*)(host_mem + seg_tss32_vm86.base); - NONFAILING( - struct tss32* tss = tss32; - memset(tss, 0, sizeof(*tss)); - tss->ss0 = tss->ss1 = tss->ss2 = SEL_DS32; - tss->sp0 = tss->sp1 = tss->sp2 = ADDR_STACK0; - tss->ip = ADDR_VAR_USER_CODE; - tss->flags = (1 << 1) | (1 << 17); - tss->ldt = SEL_LDT; - tss->cr3 = sregs.cr3; - tss->io_bitmap = offsetof(struct tss32, io_bitmap)); - struct tss32* tss32_cpl3 = (struct tss32*)(host_mem + seg_tss32_2.base); - NONFAILING( - struct tss32* tss = tss32_cpl3; - memset(tss, 0, sizeof(*tss)); - tss->ss0 = tss->ss1 = tss->ss2 = SEL_DS32; - tss->sp0 = tss->sp1 = tss->sp2 = ADDR_STACK0; - tss->ip = ADDR_VAR_USER_CODE; - tss->flags = (1 << 1); - tss->cr3 = sregs.cr3; - tss->es = tss->ds = tss->ss = tss->gs = tss->fs = SEL_DS32; - tss->cs = SEL_CS32; - tss->ldt = SEL_LDT; - tss->cr3 = sregs.cr3; - tss->io_bitmap = offsetof(struct tss32, io_bitmap)); - struct tss64* tss64 = (struct tss64*)(host_mem + seg_tss64.base); - NONFAILING( - struct tss64* tss = tss64; - memset(tss, 0, sizeof(*tss)); - tss->rsp[0] = ADDR_STACK0; - tss->rsp[1] = ADDR_STACK0; - tss->rsp[2] = ADDR_STACK0; - tss->io_bitmap = offsetof(struct tss64, io_bitmap)); - struct tss64* tss64_cpl3 = (struct tss64*)(host_mem + seg_tss64_cpl3.base); - NONFAILING( - struct tss64* tss = tss64_cpl3; - memset(tss, 0, sizeof(*tss)); - tss->rsp[0] = ADDR_STACK0; - tss->rsp[1] = ADDR_STACK0; - tss->rsp[2] = ADDR_STACK0; - tss->io_bitmap = offsetof(struct tss64, io_bitmap)); + struct tss16 tss16; + memset(&tss16, 0, sizeof(tss16)); + tss16.ss0 = tss16.ss1 = tss16.ss2 = SEL_DS16; + tss16.sp0 = tss16.sp1 = tss16.sp2 = ADDR_STACK0; + tss16.ip = ADDR_VAR_USER_CODE2; + tss16.flags = (1 << 1); + tss16.cs = SEL_CS16; + tss16.es = tss16.ds = tss16.ss = SEL_DS16; + tss16.ldt = SEL_LDT; + struct tss16* tss16_addr = (struct tss16*)(host_mem + seg_tss16_2.base); + NONFAILING(memcpy(tss16_addr, &tss16, sizeof(tss16))); + + memset(&tss16, 0, sizeof(tss16)); + tss16.ss0 = tss16.ss1 = tss16.ss2 = SEL_DS16; + tss16.sp0 = tss16.sp1 = tss16.sp2 = ADDR_STACK0; + tss16.ip = ADDR_VAR_USER_CODE2; + tss16.flags = (1 << 1); + tss16.cs = SEL_CS16_CPL3; + tss16.es = tss16.ds = tss16.ss = SEL_DS16_CPL3; + tss16.ldt = SEL_LDT; + struct tss16* tss16_cpl3_addr = (struct tss16*)(host_mem + seg_tss16_cpl3.base); + NONFAILING(memcpy(tss16_cpl3_addr, &tss16, sizeof(tss16))); + + struct tss32 tss32; + memset(&tss32, 0, sizeof(tss32)); + tss32.ss0 = tss32.ss1 = tss32.ss2 = SEL_DS32; + tss32.sp0 = tss32.sp1 = tss32.sp2 = ADDR_STACK0; + tss32.ip = ADDR_VAR_USER_CODE; + tss32.flags = (1 << 1) | (1 << 17); + tss32.ldt = SEL_LDT; + tss32.cr3 = sregs.cr3; + tss32.io_bitmap = offsetof(struct tss32, io_bitmap); + struct tss32* tss32_addr = (struct tss32*)(host_mem + seg_tss32_vm86.base); + NONFAILING(memcpy(tss32_addr, &tss32, sizeof(tss32))); + + memset(&tss32, 0, sizeof(tss32)); + tss32.ss0 = tss32.ss1 = tss32.ss2 = SEL_DS32; + tss32.sp0 = tss32.sp1 = tss32.sp2 = ADDR_STACK0; + tss32.ip = ADDR_VAR_USER_CODE; + tss32.flags = (1 << 1); + tss32.cr3 = sregs.cr3; + tss32.es = tss32.ds = tss32.ss = tss32.gs = tss32.fs = SEL_DS32; + tss32.cs = SEL_CS32; + tss32.ldt = SEL_LDT; + tss32.cr3 = sregs.cr3; + tss32.io_bitmap = offsetof(struct tss32, io_bitmap); + struct tss32* tss32_cpl3_addr = (struct tss32*)(host_mem + seg_tss32_2.base); + NONFAILING(memcpy(tss32_cpl3_addr, &tss32, sizeof(tss32))); + + struct tss64 tss64; + memset(&tss64, 0, sizeof(tss64)); + tss64.rsp[0] = ADDR_STACK0; + tss64.rsp[1] = ADDR_STACK0; + tss64.rsp[2] = ADDR_STACK0; + tss64.io_bitmap = offsetof(struct tss64, io_bitmap); + struct tss64* tss64_addr = (struct tss64*)(host_mem + seg_tss64.base); + NONFAILING(memcpy(tss64_addr, &tss64, sizeof(tss64))); + + memset(&tss64, 0, sizeof(tss64)); + tss64.rsp[0] = ADDR_STACK0; + tss64.rsp[1] = ADDR_STACK0; + tss64.rsp[2] = ADDR_STACK0; + tss64.io_bitmap = offsetof(struct tss64, io_bitmap); + struct tss64* tss64_cpl3_addr = (struct tss64*)(host_mem + seg_tss64_cpl3.base); + NONFAILING(memcpy(tss64_cpl3_addr, &tss64, sizeof(tss64))); if (text_size > 1000) text_size = 1000; @@ -1466,10 +1442,10 @@ static uintptr_t syz_kvm_setup_cpu(uintptr_t a0, uintptr_t a1, uintptr_t a2, uin val &= ((1 << 8) | (1 << 9) | (1 << 10) | (1 << 12) | (1 << 13) | (1 << 14) | (1 << 15) | (1 << 18) | (1 << 19) | (1 << 20) | (1 << 21)); regs.rflags ^= val; - NONFAILING(tss16->flags ^= val); - NONFAILING(tss16_cpl3->flags ^= val); - NONFAILING(tss32->flags ^= val); - NONFAILING(tss32_cpl3->flags ^= val); + NONFAILING(tss16_addr->flags ^= val); + NONFAILING(tss16_cpl3_addr->flags ^= val); + NONFAILING(tss32_addr->flags ^= val); + NONFAILING(tss32_cpl3_addr->flags ^= val); break; case 4: seg_cs16.type = val & 0xf; @@ -1795,9 +1771,7 @@ static int namespace_sandbox_proc(void* arg) if (mkdir("./syz-tmp/pivot", 0777)) fail("mkdir failed"); if (syscall(SYS_pivot_root, "./syz-tmp", "./syz-tmp/pivot")) { -#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("pivot_root failed"); -#endif if (chdir("./syz-tmp")) fail("chdir failed"); } else { @@ -1867,22 +1841,16 @@ retry: } int i; for (i = 0;; i++) { -#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("unlink(%s)\n", filename); -#endif if (unlink(filename) == 0) break; if (errno == EROFS) { -#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("ignoring EROFS\n"); -#endif break; } if (errno != EBUSY || i > 100) exitf("unlink(%s) failed", filename); -#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("umount(%s)\n", filename); -#endif if (umount2(filename, MNT_DETACH)) exitf("umount(%s) failed", filename); } @@ -1890,22 +1858,16 @@ retry: closedir(dp); int i; for (i = 0;; i++) { -#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("rmdir(%s)\n", dir); -#endif if (rmdir(dir) == 0) break; if (i < 100) { if (errno == EROFS) { -#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("ignoring EROFS\n"); -#endif break; } if (errno == EBUSY) { -#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("umount(%s)\n", dir); -#endif if (umount2(dir, MNT_DETACH)) exitf("umount(%s) failed", dir); continue; diff --git a/csource/csource.go b/csource/csource.go index 45a52dcf7..6caac68bf 100644 --- a/csource/csource.go +++ b/csource/csource.go @@ -14,6 +14,7 @@ import ( "io/ioutil" "os" "os/exec" + "regexp" "strings" "unsafe" @@ -144,16 +145,31 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) { fmt.Fprint(w, "\treturn 0;\n}\n") } } + + // Remove NONFAILING and debug calls. + out0 := w.String() + if !opts.HandleSegv { + re := regexp.MustCompile(`\t*NONFAILING\((.*)\);\n`) + out0 = re.ReplaceAllString(out0, "$1;\n") + } + if !opts.Debug { + re := regexp.MustCompile(`\t*debug\(.*\);\n`) + out0 = re.ReplaceAllString(out0, "") + re = regexp.MustCompile(`\t*debug_dump_data\(.*\);\n`) + out0 = re.ReplaceAllString(out0, "") + } + // Remove duplicate new lines. - out := w.Bytes() + out1 := []byte(out0) for { - out1 := bytes.Replace(out, []byte{'\n', '\n', '\n'}, []byte{'\n', '\n'}, -1) - if len(out) == len(out1) { + out2 := bytes.Replace(out1, []byte{'\n', '\n', '\n'}, []byte{'\n', '\n'}, -1) + if len(out1) == len(out2) { break } - out = out1 + out1 = out2 } - return out, nil + + return out1, nil } func generateTestFunc(w io.Writer, opts Options, calls []string, name string) { @@ -225,10 +241,6 @@ 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 @@ -257,12 +269,12 @@ loop: bfOff := read() bfLen := read() if bfOff == 0 && bfLen == 0 { - 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) + fmt.Fprintf(w, "\tNONFAILING(*(uint%v_t*)0x%x = (uint%v_t)0x%x);\n", size*8, addr, size*8, arg) } else { - 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) + fmt.Fprintf(w, "\tNONFAILING(STORE_BY_BITMASK(uint%v_t, 0x%x, 0x%x, %v, %v));\n", size*8, addr, arg, bfOff, bfLen) } case prog.ExecArgResult: - fmt.Fprintf(w, "\t%s*(uint%v_t*)0x%x = %v%s;\n", nonfailPre, size*8, addr, resultRef(), nonfailPost) + fmt.Fprintf(w, "\tNONFAILING(*(uint%v_t*)0x%x = %v);\n", size*8, addr, resultRef()) case prog.ExecArgData: data := exec[:size] exec = exec[(size+7)/8*8:] @@ -276,7 +288,7 @@ loop: } esc = append(esc, '\\', 'x', hex(v>>4), hex(v<<4>>4)) } - fmt.Fprintf(w, "\t%smemcpy((void*)0x%x, \"%s\", %v)%s;\n", nonfailPre, addr, esc, size, nonfailPost) + fmt.Fprintf(w, "\tNONFAILING(memcpy((void*)0x%x, \"%s\", %v));\n", addr, esc, size) case prog.ExecArgCsum: csum_kind := read() switch csum_kind { @@ -290,7 +302,7 @@ loop: chunk_size := read() switch chunk_kind { case prog.ExecArgCsumChunkData: - fmt.Fprintf(w, "\t%scsum_inet_update(&csum_%d, (const uint8_t*)0x%x, %d)%s;\n", nonfailPre, n, chunk_value, chunk_size, nonfailPost) + fmt.Fprintf(w, "\tNONFAILING(csum_inet_update(&csum_%d, (const uint8_t*)0x%x, %d));\n", n, chunk_value, chunk_size) 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) @@ -298,7 +310,7 @@ loop: panic(fmt.Sprintf("unknown checksum chunk kind %v", chunk_kind)) } } - fmt.Fprintf(w, "\t%s*(uint16_t*)0x%x = csum_inet_digest(&csum_%d)%s;\n", nonfailPre, addr, n, nonfailPost) + fmt.Fprintf(w, "\tNONFAILING(*(uint16_t*)0x%x = csum_inet_digest(&csum_%d));\n", addr, n) default: panic(fmt.Sprintf("unknown csum kind %v", csum_kind)) } @@ -309,7 +321,7 @@ loop: addr := read() size := read() fmt.Fprintf(w, "\tif (r[%v] != -1)\n", lastCall) - fmt.Fprintf(w, "\t\t%sr[%v] = *(uint%v_t*)0x%x%s;\n", nonfailPre, n, size*8, addr, nonfailPost) + fmt.Fprintf(w, "\t\tNONFAILING(r[%v] = *(uint%v_t*)0x%x);\n", n, size*8, addr) default: // Normal syscall. newCall() diff --git a/executor/common.h b/executor/common.h index 1be840bc4..7778cb7e0 100644 --- a/executor/common.h +++ b/executor/common.h @@ -257,14 +257,10 @@ static void segv_handler(int sig, siginfo_t* info, void* uctx) const uintptr_t prog_start = 1 << 20; const uintptr_t prog_end = 100 << 20; if (__atomic_load_n(&skip_segv, __ATOMIC_RELAXED) && (addr < prog_start || addr > prog_end)) { -#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("SIGSEGV on %p, skipping\n", addr); -#endif _longjmp(segv_env, 1); } -#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("SIGSEGV on %p, exiting\n", addr); -#endif doexit(sig); for (;;) { } @@ -497,9 +493,7 @@ static uintptr_t syz_emit_ethernet(uintptr_t a0, uintptr_t a1) int64_t length = a0; char* data = (char*)a1; -#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug_dump_data(data, length); -#endif return write(tunfd, data, length); } #endif @@ -546,9 +540,7 @@ static uintptr_t syz_extract_tcp_res(uintptr_t a0, uintptr_t a1, uintptr_t a2) if (rv == -1) return (uintptr_t)-1; size_t length = rv; -#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug_dump_data(data, length); -#endif struct tcphdr* tcphdr; @@ -578,18 +570,11 @@ 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 -#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("extracted seq: %08x\n", res->seq); debug("extracted ack: %08x\n", res->ack); -#endif return 0; } @@ -608,11 +593,7 @@ static uintptr_t syz_open_dev(uintptr_t a0, uintptr_t a1, uintptr_t a2) // syz_open_dev(dev strconst, id intptr, flags flags[open_flags]) fd 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); // 10 devices should be enough for everyone. @@ -890,9 +871,7 @@ static int namespace_sandbox_proc(void* arg) if (mkdir("./syz-tmp/pivot", 0777)) fail("mkdir failed"); if (syscall(SYS_pivot_root, "./syz-tmp", "./syz-tmp/pivot")) { -#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("pivot_root failed"); -#endif if (chdir("./syz-tmp")) fail("chdir failed"); } else { @@ -974,22 +953,16 @@ retry: } int i; for (i = 0;; i++) { -#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("unlink(%s)\n", filename); -#endif if (unlink(filename) == 0) break; if (errno == EROFS) { -#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("ignoring EROFS\n"); -#endif break; } if (errno != EBUSY || i > 100) exitf("unlink(%s) failed", filename); -#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("umount(%s)\n", filename); -#endif if (umount2(filename, MNT_DETACH)) exitf("umount(%s) failed", filename); } @@ -997,22 +970,16 @@ retry: closedir(dp); int i; for (i = 0;; i++) { -#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("rmdir(%s)\n", dir); -#endif if (rmdir(dir) == 0) break; if (i < 100) { if (errno == EROFS) { -#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("ignoring EROFS\n"); -#endif break; } if (errno == EBUSY) { -#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) debug("umount(%s)\n", dir); -#endif if (umount2(dir, MNT_DETACH)) exitf("umount(%s) failed", dir); continue; diff --git a/executor/common_kvm_amd64.h b/executor/common_kvm_amd64.h index e4753223e..5dce25311 100644 --- a/executor/common_kvm_amd64.h +++ b/executor/common_kvm_amd64.h @@ -7,15 +7,6 @@ // See Intel Software Developer’s Manual Volume 3: System Programming Guide // for details on what happens here. -// We could put each NONFAILING use in this file under ifdef, -// but I don't think it's worth it. -#ifndef NONFAILING -#define NONFAILING(x) \ - { \ - x; \ - } -#endif - #include "kvm.S.h" #include "kvm.h" @@ -632,69 +623,71 @@ static uintptr_t syz_kvm_setup_cpu(uintptr_t a0, uintptr_t a1, uintptr_t a2, uin } } - struct tss16* tss16 = (struct tss16*)(host_mem + seg_tss16_2.base); - NONFAILING( - struct tss16* tss = tss16; - memset(tss, 0, sizeof(*tss)); - tss->ss0 = tss->ss1 = tss->ss2 = SEL_DS16; - tss->sp0 = tss->sp1 = tss->sp2 = ADDR_STACK0; - tss->ip = ADDR_VAR_USER_CODE2; - tss->flags = (1 << 1); - tss->cs = SEL_CS16; - tss->es = tss->ds = tss->ss = SEL_DS16; - tss->ldt = SEL_LDT); - struct tss16* tss16_cpl3 = (struct tss16*)(host_mem + seg_tss16_cpl3.base); - NONFAILING( - struct tss16* tss = tss16_cpl3; - memset(tss, 0, sizeof(*tss)); - tss->ss0 = tss->ss1 = tss->ss2 = SEL_DS16; - tss->sp0 = tss->sp1 = tss->sp2 = ADDR_STACK0; - tss->ip = ADDR_VAR_USER_CODE2; - tss->flags = (1 << 1); - tss->cs = SEL_CS16_CPL3; - tss->es = tss->ds = tss->ss = SEL_DS16_CPL3; - tss->ldt = SEL_LDT); - struct tss32* tss32 = (struct tss32*)(host_mem + seg_tss32_vm86.base); - NONFAILING( - struct tss32* tss = tss32; - memset(tss, 0, sizeof(*tss)); - tss->ss0 = tss->ss1 = tss->ss2 = SEL_DS32; - tss->sp0 = tss->sp1 = tss->sp2 = ADDR_STACK0; - tss->ip = ADDR_VAR_USER_CODE; - tss->flags = (1 << 1) | (1 << 17); - tss->ldt = SEL_LDT; - tss->cr3 = sregs.cr3; - tss->io_bitmap = offsetof(struct tss32, io_bitmap)); - struct tss32* tss32_cpl3 = (struct tss32*)(host_mem + seg_tss32_2.base); - NONFAILING( - struct tss32* tss = tss32_cpl3; - memset(tss, 0, sizeof(*tss)); - tss->ss0 = tss->ss1 = tss->ss2 = SEL_DS32; - tss->sp0 = tss->sp1 = tss->sp2 = ADDR_STACK0; - tss->ip = ADDR_VAR_USER_CODE; - tss->flags = (1 << 1); - tss->cr3 = sregs.cr3; - tss->es = tss->ds = tss->ss = tss->gs = tss->fs = SEL_DS32; - tss->cs = SEL_CS32; - tss->ldt = SEL_LDT; - tss->cr3 = sregs.cr3; - tss->io_bitmap = offsetof(struct tss32, io_bitmap)); - struct tss64* tss64 = (struct tss64*)(host_mem + seg_tss64.base); - NONFAILING( - struct tss64* tss = tss64; - memset(tss, 0, sizeof(*tss)); - tss->rsp[0] = ADDR_STACK0; - tss->rsp[1] = ADDR_STACK0; - tss->rsp[2] = ADDR_STACK0; - tss->io_bitmap = offsetof(struct tss64, io_bitmap)); - struct tss64* tss64_cpl3 = (struct tss64*)(host_mem + seg_tss64_cpl3.base); - NONFAILING( - struct tss64* tss = tss64_cpl3; - memset(tss, 0, sizeof(*tss)); - tss->rsp[0] = ADDR_STACK0; - tss->rsp[1] = ADDR_STACK0; - tss->rsp[2] = ADDR_STACK0; - tss->io_bitmap = offsetof(struct tss64, io_bitmap)); + struct tss16 tss16; + memset(&tss16, 0, sizeof(tss16)); + tss16.ss0 = tss16.ss1 = tss16.ss2 = SEL_DS16; + tss16.sp0 = tss16.sp1 = tss16.sp2 = ADDR_STACK0; + tss16.ip = ADDR_VAR_USER_CODE2; + tss16.flags = (1 << 1); + tss16.cs = SEL_CS16; + tss16.es = tss16.ds = tss16.ss = SEL_DS16; + tss16.ldt = SEL_LDT; + struct tss16* tss16_addr = (struct tss16*)(host_mem + seg_tss16_2.base); + NONFAILING(memcpy(tss16_addr, &tss16, sizeof(tss16))); + + memset(&tss16, 0, sizeof(tss16)); + tss16.ss0 = tss16.ss1 = tss16.ss2 = SEL_DS16; + tss16.sp0 = tss16.sp1 = tss16.sp2 = ADDR_STACK0; + tss16.ip = ADDR_VAR_USER_CODE2; + tss16.flags = (1 << 1); + tss16.cs = SEL_CS16_CPL3; + tss16.es = tss16.ds = tss16.ss = SEL_DS16_CPL3; + tss16.ldt = SEL_LDT; + struct tss16* tss16_cpl3_addr = (struct tss16*)(host_mem + seg_tss16_cpl3.base); + NONFAILING(memcpy(tss16_cpl3_addr, &tss16, sizeof(tss16))); + + struct tss32 tss32; + memset(&tss32, 0, sizeof(tss32)); + tss32.ss0 = tss32.ss1 = tss32.ss2 = SEL_DS32; + tss32.sp0 = tss32.sp1 = tss32.sp2 = ADDR_STACK0; + tss32.ip = ADDR_VAR_USER_CODE; + tss32.flags = (1 << 1) | (1 << 17); + tss32.ldt = SEL_LDT; + tss32.cr3 = sregs.cr3; + tss32.io_bitmap = offsetof(struct tss32, io_bitmap); + struct tss32* tss32_addr = (struct tss32*)(host_mem + seg_tss32_vm86.base); + NONFAILING(memcpy(tss32_addr, &tss32, sizeof(tss32))); + + memset(&tss32, 0, sizeof(tss32)); + tss32.ss0 = tss32.ss1 = tss32.ss2 = SEL_DS32; + tss32.sp0 = tss32.sp1 = tss32.sp2 = ADDR_STACK0; + tss32.ip = ADDR_VAR_USER_CODE; + tss32.flags = (1 << 1); + tss32.cr3 = sregs.cr3; + tss32.es = tss32.ds = tss32.ss = tss32.gs = tss32.fs = SEL_DS32; + tss32.cs = SEL_CS32; + tss32.ldt = SEL_LDT; + tss32.cr3 = sregs.cr3; + tss32.io_bitmap = offsetof(struct tss32, io_bitmap); + struct tss32* tss32_cpl3_addr = (struct tss32*)(host_mem + seg_tss32_2.base); + NONFAILING(memcpy(tss32_cpl3_addr, &tss32, sizeof(tss32))); + + struct tss64 tss64; + memset(&tss64, 0, sizeof(tss64)); + tss64.rsp[0] = ADDR_STACK0; + tss64.rsp[1] = ADDR_STACK0; + tss64.rsp[2] = ADDR_STACK0; + tss64.io_bitmap = offsetof(struct tss64, io_bitmap); + struct tss64* tss64_addr = (struct tss64*)(host_mem + seg_tss64.base); + NONFAILING(memcpy(tss64_addr, &tss64, sizeof(tss64))); + + memset(&tss64, 0, sizeof(tss64)); + tss64.rsp[0] = ADDR_STACK0; + tss64.rsp[1] = ADDR_STACK0; + tss64.rsp[2] = ADDR_STACK0; + tss64.io_bitmap = offsetof(struct tss64, io_bitmap); + struct tss64* tss64_cpl3_addr = (struct tss64*)(host_mem + seg_tss64_cpl3.base); + NONFAILING(memcpy(tss64_cpl3_addr, &tss64, sizeof(tss64))); if (text_size > 1000) text_size = 1000; @@ -747,10 +740,10 @@ static uintptr_t syz_kvm_setup_cpu(uintptr_t a0, uintptr_t a1, uintptr_t a2, uin val &= ((1 << 8) | (1 << 9) | (1 << 10) | (1 << 12) | (1 << 13) | (1 << 14) | (1 << 15) | (1 << 18) | (1 << 19) | (1 << 20) | (1 << 21)); regs.rflags ^= val; - NONFAILING(tss16->flags ^= val); - NONFAILING(tss16_cpl3->flags ^= val); - NONFAILING(tss32->flags ^= val); - NONFAILING(tss32_cpl3->flags ^= val); + NONFAILING(tss16_addr->flags ^= val); + NONFAILING(tss16_cpl3_addr->flags ^= val); + NONFAILING(tss32_addr->flags ^= val); + NONFAILING(tss32_cpl3_addr->flags ^= val); break; case 4: seg_cs16.type = val & 0xf; -- cgit mrf-deployment