aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--executor/common.h107
-rw-r--r--executor/common_akaros.h9
-rw-r--r--executor/common_bsd.h6
-rw-r--r--executor/common_fuchsia.h3
-rw-r--r--executor/common_linux.h27
-rw-r--r--executor/common_test.h6
-rw-r--r--executor/common_windows.h17
-rw-r--r--executor/executor.cc1
-rw-r--r--pkg/csource/common.go36
-rw-r--r--pkg/csource/csource.go208
-rw-r--r--pkg/csource/generated.go172
11 files changed, 367 insertions, 225 deletions
diff --git a/executor/common.h b/executor/common.h
index 5ddfb08c5..9e6545926 100644
--- a/executor/common.h
+++ b/executor/common.h
@@ -2,6 +2,14 @@
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
// This file is shared between executor and csource package.
+// csource does a bunch of transformations with this file:
+// - unused parts are stripped using #if SYZ* defines
+// - includes are hoisted to the top and deduplicated
+// - comments and empty lines are stripped
+// - NORETURN/PRINTF/debug are removed
+// - exitf/failf/fail are replaced with exit
+// - uintN types are replaced with uintN_t
+// - [[FOO]] placeholders are replaced by actual values
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
@@ -23,6 +31,11 @@ NORETURN void doexit(int status)
}
#endif
+#if SYZ_EXECUTOR || SYZ_PROCS || SYZ_REPEAT && SYZ_ENABLE_CGROUPS || \
+ __NR_syz_mount_image || __NR_syz_read_part_table
+unsigned long long procid;
+#endif
+
#if !GOOS_fuchsia && !GOOS_windows
#if SYZ_EXECUTOR || SYZ_HANDLE_SEGV
#include <setjmp.h>
@@ -359,9 +372,6 @@ struct thread_t {
static struct thread_t threads[16];
static void execute_call(int call);
static int running;
-#if SYZ_COLLIDE
-static int collide;
-#endif
static void* thr(void* arg)
{
@@ -376,11 +386,22 @@ static void* thr(void* arg)
return 0;
}
-static void execute(int num_calls)
+#if SYZ_REPEAT
+static void execute_one()
+#else
+static void loop()
+#endif
{
+#if SYZ_REPRO
+ if (write(1, "executing program\n", sizeof("executing program\n") - 1)) {
+ }
+#endif
int call, thread;
- running = 0;
- for (call = 0; call < num_calls; call++) {
+#if SYZ_COLLIDE
+ int collide = 0;
+again:
+#endif
+ for (call = 0; call < [[NUM_CALLS]]; call++) {
for (thread = 0; thread < sizeof(threads) / sizeof(threads[0]); thread++) {
struct thread_t* th = &threads[thread];
if (!th->created) {
@@ -402,10 +423,16 @@ static void execute(int num_calls)
#endif
event_timedwait(&th->done, 25);
if (__atomic_load_n(&running, __ATOMIC_RELAXED))
- sleep_ms((call == num_calls - 1) ? 10 : 2);
+ sleep_ms((call == [[NUM_CALLS]] - 1) ? 10 : 2);
break;
}
}
+#if SYZ_COLLIDE
+ if (!collide) {
+ collide = 1;
+ goto again;
+ }
+#endif
}
#endif
@@ -428,7 +455,9 @@ static void reply_handshake();
static void loop()
{
+#if SYZ_HAVE_SETUP_LOOP
setup_loop();
+#endif
#if SYZ_EXECUTOR
// Tell parent that we are ready to serve.
reply_handshake();
@@ -449,7 +478,9 @@ static void loop()
if (mkdir(cwdbuf, 0777))
fail("failed to mkdir");
#endif
+#if SYZ_HAVE_RESET_LOOP
reset_loop();
+#endif
#if SYZ_EXECUTOR
receive_execute();
#endif
@@ -457,7 +488,9 @@ static void loop()
if (pid < 0)
fail("clone failed");
if (pid == 0) {
+#if SYZ_HAVE_SETUP_TEST
setup_test();
+#endif
#if SYZ_EXECUTOR || SYZ_USE_TMP_DIR
if (chdir(cwdbuf))
fail("failed to chdir");
@@ -479,7 +512,9 @@ static void loop()
#endif
execute_one();
debug("worker exiting\n");
+#if SYZ_HAVE_RESET_TEST
reset_test();
+#endif
doexit(0);
#endif
}
@@ -556,3 +591,61 @@ static void loop()
}
#endif
#endif
+
+#if !SYZ_EXECUTOR
+[[SYSCALL_DEFINES]]
+
+[[RESULTS]]
+
+#if SYZ_THREADED || SYZ_REPEAT || SYZ_SANDBOX_NONE || SYZ_SANDBOX_SETUID || SYZ_SANDBOX_NAMESPACE
+#if SYZ_THREADED
+void
+execute_call(int call)
+#elif SYZ_REPEAT
+void
+execute_one()
+#else
+void
+loop()
+#endif
+{
+ [[SYSCALLS]]
+}
+#endif
+
+// This is the main function for csource.
+#if GOOS_akaros && SYZ_REPEAT
+#include <string.h>
+
+int main(int argc, char** argv)
+{
+ [[MMAP_DATA]]
+
+ program_name = argv[0];
+ if (argc == 2 && strcmp(argv[1], "child") == 0)
+ child();
+#else
+int
+main()
+{
+ [[MMAP_DATA]]
+#endif
+#if SYZ_HANDLE_SEGV
+ install_segv_handler();
+#endif
+#if SYZ_PROCS
+ for (procid = 0; procid < [[PROCS]]; procid++) {
+ if (fork() == 0) {
+#endif
+#if SYZ_USE_TMP_DIR
+ use_temporary_dir();
+#endif
+ [[SANDBOX_FUNC]]
+#if SYZ_PROCS
+ }
+ }
+ sleep(1000000);
+#endif
+ return 0;
+}
+#endif
diff --git a/executor/common_akaros.h b/executor/common_akaros.h
index f2f89033e..a0e42088a 100644
--- a/executor/common_akaros.h
+++ b/executor/common_akaros.h
@@ -3,9 +3,8 @@
// This file is shared between executor and csource package.
+#include <ros/syscall.h>
#include <stdlib.h>
-#include <sys/mman.h>
-#include <sys/syscall.h>
#include <unistd.h>
#if SYZ_EXECUTOR || SYZ_SANDBOX_NONE
@@ -35,9 +34,7 @@ void child()
}
#endif
+#if SYZ_EXECUTOR
#define do_sandbox_setuid() 0
#define do_sandbox_namespace() 0
-#define setup_loop()
-#define reset_loop()
-#define setup_test()
-#define reset_test()
+#endif
diff --git a/executor/common_bsd.h b/executor/common_bsd.h
index 164d16a36..b678dd968 100644
--- a/executor/common_bsd.h
+++ b/executor/common_bsd.h
@@ -14,9 +14,7 @@ static int do_sandbox_none(void)
}
#endif
+#if SYZ_EXECUTOR
#define do_sandbox_setuid() 0
#define do_sandbox_namespace() 0
-#define setup_loop()
-#define reset_loop()
-#define setup_test()
-#define reset_test()
+#endif
diff --git a/executor/common_fuchsia.h b/executor/common_fuchsia.h
index 1affa5650..302f49955 100644
--- a/executor/common_fuchsia.h
+++ b/executor/common_fuchsia.h
@@ -237,8 +237,11 @@ static int do_sandbox_none(void)
}
#endif
+#if SYZ_EXECUTOR
#define do_sandbox_setuid() 0
#define do_sandbox_namespace() 0
+#endif
+
#define setup_loop()
#define reset_loop()
#define setup_test()
diff --git a/executor/common_linux.h b/executor/common_linux.h
index ad653f396..4ff59aa80 100644
--- a/executor/common_linux.h
+++ b/executor/common_linux.h
@@ -4,7 +4,6 @@
// This file is shared between executor and csource package.
#include <stdlib.h>
-#include <sys/mount.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
@@ -641,8 +640,6 @@ static long syz_genetlink_get_family_id(long name)
#include <sys/stat.h>
#include <sys/types.h>
-extern unsigned long long procid;
-
struct fs_image_segment {
void* data;
uintptr_t size;
@@ -758,6 +755,9 @@ error:
#endif
#if SYZ_EXECUTOR || __NR_syz_mount_image
+#include <string.h>
+#include <sys/mount.h>
+
//syz_mount_image(fs ptr[in, string[disk_filesystems]], dir ptr[in, filename], size intptr, nsegs len[segments], segments ptr[in, array[fs_image_segment]], flags flags[mount_flags], opts ptr[in, fs_options[vfat_options]])
//fs_image_segment {
// data ptr[in, array[int8]]
@@ -885,6 +885,7 @@ static long syz_kvm_setup_cpu(long a0, long a1, long a2, long a3, long a4, long
#include <fcntl.h>
#include <stdarg.h>
#include <stdbool.h>
+#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -916,6 +917,7 @@ static bool write_file(const char* file, const char* what, ...)
#include <errno.h>
#include <linux/net.h>
#include <netinet/in.h>
+#include <string.h>
#include <sys/socket.h>
// checkpoint/reset_net_namespace partially resets net namespace to initial state
@@ -1572,6 +1574,7 @@ static int do_sandbox_setuid(void)
#include <linux/capability.h>
#include <sched.h>
#include <sys/mman.h>
+#include <sys/mount.h>
static int real_uid;
static int real_gid;
@@ -1706,6 +1709,8 @@ static int do_sandbox_namespace(void)
#if SYZ_EXECUTOR || SYZ_REPEAT && SYZ_USE_TMP_DIR
#include <dirent.h>
#include <errno.h>
+#include <string.h>
+#include <sys/mount.h>
// One does not simply remove a directory.
// There can be mounts, so we need to try to umount.
@@ -1795,6 +1800,7 @@ retry:
#if SYZ_EXECUTOR || SYZ_FAULT_INJECTION
#include <fcntl.h>
+#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -1832,16 +1838,14 @@ static int fault_injected(int fail_fd)
}
#endif
-#if SYZ_EXECUTOR || SYZ_REPEAT
+#if SYZ_EXECUTOR || SYZ_REPEAT && SYZ_ENABLE_CGROUPS
#include <fcntl.h>
#include <sys/ioctl.h>
-#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
-extern unsigned long long procid;
-
+#define SYZ_HAVE_SETUP_LOOP 1
static void setup_loop()
{
#if SYZ_ENABLE_CGROUPS
@@ -1874,7 +1878,10 @@ static void setup_loop()
}
#endif
}
+#endif
+#if SYZ_EXECUTOR || SYZ_REPEAT && (SYZ_RESET_NET_NAMESPACE || __NR_syz_mount_image || __NR_syz_read_part_table)
+#define SYZ_HAVE_RESET_LOOP 1
static void reset_loop()
{
#if SYZ_EXECUTOR || __NR_syz_mount_image || __NR_syz_read_part_table
@@ -1890,7 +1897,12 @@ static void reset_loop()
reset_net_namespace();
#endif
}
+#endif
+
+#if SYZ_EXECUTOR || SYZ_REPEAT
+#include <sys/prctl.h>
+#define SYZ_HAVE_SETUP_TEST 1
static void setup_test()
{
prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
@@ -1917,6 +1929,7 @@ static void setup_test()
#endif
}
+#define SYZ_HAVE_RESET_TEST 1
static void reset_test()
{
// Keeping a 9p transport pipe open will hang the proccess dead,
diff --git a/executor/common_test.h b/executor/common_test.h
index 38accf58a..78b3f8e22 100644
--- a/executor/common_test.h
+++ b/executor/common_test.h
@@ -22,9 +22,7 @@ static int do_sandbox_none(void)
}
#endif
+#if SYZ_EXECUTOR
#define do_sandbox_setuid() 0
#define do_sandbox_namespace() 0
-#define setup_loop()
-#define reset_loop()
-#define setup_test()
-#define reset_test()
+#endif
diff --git a/executor/common_windows.h b/executor/common_windows.h
index c4fdcd66f..1aada0933 100644
--- a/executor/common_windows.h
+++ b/executor/common_windows.h
@@ -103,7 +103,16 @@ static int event_timedwait(event_t* ev, uint64 timeout_ms)
}
#endif
-#define setup_loop()
-#define reset_loop()
-#define setup_test()
-#define reset_test()
+#if SYZ_EXECUTOR || SYZ_SANDBOX_NONE
+static void loop();
+static int do_sandbox_none(void)
+{
+ loop();
+ doexit(0);
+}
+#endif
+
+#if SYZ_EXECUTOR
+#define do_sandbox_setuid() 0
+#define do_sandbox_namespace() 0
+#endif
diff --git a/executor/executor.cc b/executor/executor.cc
index 1efba1060..c5b9efe42 100644
--- a/executor/executor.cc
+++ b/executor/executor.cc
@@ -146,7 +146,6 @@ const uint64 binary_format_stroct = 4;
const uint64 no_copyout = -1;
-unsigned long long procid;
int running;
uint32 completed;
bool collide;
diff --git a/pkg/csource/common.go b/pkg/csource/common.go
index 5f0cc4221..ebc085c7a 100644
--- a/pkg/csource/common.go
+++ b/pkg/csource/common.go
@@ -25,7 +25,7 @@ const (
sandboxNamespace = "namespace"
)
-func createCommonHeader(p, mmapProg *prog.Prog, opts Options) ([]byte, error) {
+func createCommonHeader(p, mmapProg *prog.Prog, replacements map[string]string, opts Options) ([]byte, error) {
defines, err := defineList(p, mmapProg, opts)
if err != nil {
return nil, err
@@ -49,6 +49,10 @@ func createCommonHeader(p, mmapProg *prog.Prog, opts Options) ([]byte, error) {
return nil, err
}
+ for from, to := range replacements {
+ src = bytes.Replace(src, []byte("[["+from+"]]"), []byte(to), -1)
+ }
+
for from, to := range map[string]string{
"uint64": "uint64_t",
"uint32": "uint32_t",
@@ -91,6 +95,9 @@ func defineList(p, mmapProg *prog.Prog, opts Options) ([]string, error) {
if opts.Repeat {
defines = append(defines, "SYZ_REPEAT")
}
+ if opts.Procs > 1 {
+ defines = append(defines, "SYZ_PROCS")
+ }
if opts.Fault {
defines = append(defines, "SYZ_FAULT_INJECTION")
}
@@ -112,6 +119,9 @@ func defineList(p, mmapProg *prog.Prog, opts Options) ([]string, error) {
if opts.HandleSegv {
defines = append(defines, "SYZ_HANDLE_SEGV")
}
+ if opts.Repro {
+ defines = append(defines, "SYZ_REPRO")
+ }
for _, c := range p.Calls {
defines = append(defines, "__NR_"+c.Meta.CallName)
}
@@ -131,14 +141,22 @@ func defineList(p, mmapProg *prog.Prog, opts Options) ([]string, error) {
}
func removeSystemDefines(src []byte, defines []string) ([]byte, error) {
- remove := append(defines, []string{
- "__STDC__",
- "__STDC_HOSTED__",
- "__STDC_UTF_16__",
- "__STDC_UTF_32__",
- }...)
- for _, def := range remove {
- src = bytes.Replace(src, []byte("#define "+def+" 1\n"), nil, -1)
+ remove := map[string]string{
+ "__STDC__": "1",
+ "__STDC_HOSTED__": "1",
+ "__STDC_UTF_16__": "1",
+ "__STDC_UTF_32__": "1",
+ }
+ for _, def := range defines {
+ eq := strings.IndexByte(def, '=')
+ if eq == -1 {
+ remove[def] = "1"
+ } else {
+ remove[def[:eq]] = def[eq+1:]
+ }
+ }
+ for def, val := range remove {
+ src = bytes.Replace(src, []byte("#define "+def+" "+val+"\n"), nil, -1)
}
// strip: #define __STDC_VERSION__ 201112L
for _, def := range []string{"__STDC_VERSION__"} {
diff --git a/pkg/csource/csource.go b/pkg/csource/csource.go
index 512d9985a..66958f22b 100644
--- a/pkg/csource/csource.go
+++ b/pkg/csource/csource.go
@@ -24,7 +24,6 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) {
opts: opts,
target: p.Target,
sysTarget: targets.Get(p.Target.OS, p.Target.Arch),
- w: new(bytes.Buffer),
calls: make(map[string]uint64),
}
@@ -43,100 +42,43 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) {
ctx.calls[c.Meta.CallName] = c.Meta.NR
}
- ctx.print("// autogenerated by syzkaller (http://github.com/google/syzkaller)\n\n")
-
- hdr, err := createCommonHeader(p, mmapProg, opts)
- if err != nil {
- return nil, err
- }
- ctx.w.Write(hdr)
- ctx.print("\n")
-
- ctx.generateSyscallDefines()
-
+ varsBuf := new(bytes.Buffer)
if len(vars) != 0 {
- ctx.printf("uint64_t r[%v] = {", len(vars))
+ fmt.Fprintf(varsBuf, "uint64 r[%v] = {", len(vars))
for i, v := range vars {
if i != 0 {
- ctx.printf(", ")
+ fmt.Fprintf(varsBuf, ", ")
}
- ctx.printf("0x%x", v)
+ fmt.Fprintf(varsBuf, "0x%x", v)
}
- ctx.printf("};\n")
- }
- needProcID := opts.Procs > 1 || opts.EnableCgroups
- for _, c := range p.Calls {
- if c.Meta.CallName == "syz_mount_image" ||
- c.Meta.CallName == "syz_read_part_table" {
- needProcID = true
- }
- }
- if needProcID {
- ctx.printf("unsigned long long procid;\n")
+ fmt.Fprintf(varsBuf, "};\n")
}
- if opts.Repeat {
- ctx.generateTestFunc(calls, len(vars) != 0, "execute_one")
- } else {
- ctx.generateTestFunc(calls, len(vars) != 0, "loop")
+ sandboxFunc := "loop();"
+ if opts.Sandbox != "" {
+ sandboxFunc = "do_sandbox_" + opts.Sandbox + "();"
}
-
- if ctx.target.OS == "akaros" && opts.Repeat {
- ctx.printf("const char* program_name;\n")
- ctx.print("int main(int argc, char** argv)\n{\n")
- } else {
- ctx.print("int main()\n{\n")
+ replacements := map[string]string{
+ "PROCS": fmt.Sprint(opts.Procs),
+ "NUM_CALLS": fmt.Sprint(len(p.Calls)),
+ "MMAP_DATA": strings.Join(mmapCalls, ""),
+ "SYSCALL_DEFINES": ctx.generateSyscallDefines(),
+ "SANDBOX_FUNC": sandboxFunc,
+ "RESULTS": varsBuf.String(),
+ "SYSCALLS": ctx.generateSyscalls(calls, len(vars) != 0),
}
- for _, c := range mmapCalls {
- ctx.printf("%s", c)
+ if !opts.Threaded && !opts.Repeat && opts.Sandbox == "" {
+ // This inlines syscalls right into main for the simplest case.
+ replacements["SANDBOX_FUNC"] = replacements["SYSCALLS"]
+ replacements["SYSCALLS"] = "unused"
}
- if ctx.target.OS == "akaros" && opts.Repeat {
- ctx.printf("\tprogram_name = argv[0];\n")
- ctx.printf("\tif (argc == 2 && strcmp(argv[1], \"child\") == 0)\n")
- ctx.printf("\t\tchild();\n")
- }
- if opts.HandleSegv {
- ctx.printf("\tinstall_segv_handler();\n")
- }
-
- if !opts.Repeat {
- if opts.UseTmpDir {
- ctx.printf("\tuse_temporary_dir();\n")
- }
- ctx.writeLoopCall()
- } else {
- if opts.UseTmpDir {
- ctx.print("\tchar *cwd = get_current_dir_name();\n")
- }
- if opts.Procs <= 1 {
- ctx.print("\tfor (;;) {\n")
- if opts.UseTmpDir {
- ctx.print("\t\tif (chdir(cwd))\n")
- ctx.print("\t\t\tfail(\"failed to chdir\");\n")
- ctx.print("\t\tuse_temporary_dir();\n")
- }
- ctx.writeLoopCall()
- ctx.print("\t}\n")
- } else {
- ctx.printf("\tfor (procid = 0; procid < %v; procid++) {\n", opts.Procs)
- ctx.print("\t\tif (fork() == 0) {\n")
- ctx.print("\t\t\tfor (;;) {\n")
- if opts.UseTmpDir {
- ctx.print("\t\t\t\tif (chdir(cwd))\n")
- ctx.print("\t\t\t\t\tfail(\"failed to chdir\");\n")
- ctx.print("\t\t\t\tuse_temporary_dir();\n")
- }
- ctx.writeLoopCall()
- ctx.print("\t\t\t}\n")
- ctx.print("\t\t}\n")
- ctx.print("\t}\n")
- ctx.print("\tsleep(1000000);\n")
- }
+ result, err := createCommonHeader(p, mmapProg, replacements, opts)
+ if err != nil {
+ return nil, err
}
-
- ctx.print("\treturn 0;\n}\n")
-
- result := ctx.postProcess(ctx.w.Bytes())
+ const header = "// autogenerated by syzkaller (https://github.com/google/syzkaller)\n\n"
+ result = append([]byte(header), result...)
+ result = ctx.postProcess(result)
return result, nil
}
@@ -145,92 +87,62 @@ type context struct {
opts Options
target *prog.Target
sysTarget *targets.Target
- w *bytes.Buffer
calls map[string]uint64 // CallName -> NR
}
-func (ctx *context) print(str string) {
- ctx.w.WriteString(str)
-}
-
-func (ctx *context) printf(str string, args ...interface{}) {
- ctx.print(fmt.Sprintf(str, args...))
-}
-
-func (ctx *context) writeLoopCall() {
- if ctx.opts.Sandbox != "" {
- ctx.printf("\tdo_sandbox_%v();\n", ctx.opts.Sandbox)
- return
- }
- if ctx.opts.EnableTun {
- ctx.printf("\tinitialize_tun();\n")
- }
- if ctx.opts.EnableNetdev {
- ctx.printf("\tinitialize_netdevices();\n")
- }
- ctx.print("\tloop();\n")
-}
-
-func (ctx *context) generateTestFunc(calls []string, hasVars bool, name string) {
+func (ctx *context) generateSyscalls(calls []string, hasVars bool) string {
opts := ctx.opts
+ buf := new(bytes.Buffer)
if !opts.Threaded && !opts.Collide {
- ctx.printf("void %v()\n{\n", name)
if hasVars {
- ctx.printf("\tlong res = 0;\n")
+ fmt.Fprintf(buf, "\tlong res = 0;\n")
}
if opts.Repro {
- ctx.printf("\tif (write(1, \"executing program\\n\", strlen(\"executing program\\n\"))) {}\n")
+ fmt.Fprintf(buf, "\tif (write(1, \"executing program\\n\", sizeof(\"executing program\\n\") - 1)) {}\n")
}
for _, c := range calls {
- ctx.printf("%s", c)
+ fmt.Fprintf(buf, "%s", c)
}
- ctx.printf("}\n\n")
} else {
- ctx.printf("void execute_call(int call)\n{\n")
if hasVars {
- ctx.printf("\tlong res;")
+ fmt.Fprintf(buf, "\tlong res;")
}
- ctx.printf("\tswitch (call) {\n")
+ fmt.Fprintf(buf, "\tswitch (call) {\n")
for i, c := range calls {
- ctx.printf("\tcase %v:\n", i)
- ctx.printf("%s", strings.Replace(c, "\t", "\t\t", -1))
- ctx.printf("\t\tbreak;\n")
- }
- ctx.printf("\t}\n")
- ctx.printf("}\n\n")
-
- ctx.printf("void %v()\n{\n", name)
- if opts.Repro {
- ctx.printf("\tif (write(1, \"executing program\\n\", strlen(\"executing program\\n\"))) {}\n")
- }
- ctx.printf("\texecute(%v);\n", len(calls))
- if opts.Collide {
- ctx.printf("\tcollide = 1;\n")
- ctx.printf("\texecute(%v);\n", len(calls))
+ fmt.Fprintf(buf, "\tcase %v:\n", i)
+ fmt.Fprintf(buf, "%s", strings.Replace(c, "\t", "\t\t", -1))
+ fmt.Fprintf(buf, "\t\tbreak;\n")
}
- ctx.printf("}\n\n")
+ fmt.Fprintf(buf, "\t}\n")
}
+ return buf.String()
}
-func (ctx *context) generateSyscallDefines() {
- prefix := ctx.sysTarget.SyscallPrefix
+func (ctx *context) generateSyscallDefines() string {
+ var calls []string
for name, nr := range ctx.calls {
if !ctx.sysTarget.SyscallNumbers ||
strings.HasPrefix(name, "syz_") || !ctx.sysTarget.NeedSyscallDefine(nr) {
continue
}
- ctx.printf("#ifndef %v%v\n", prefix, name)
- ctx.printf("#define %v%v %v\n", prefix, name, nr)
- ctx.printf("#endif\n")
+ calls = append(calls, name)
+ }
+ sort.Strings(calls)
+ buf := new(bytes.Buffer)
+ prefix := ctx.sysTarget.SyscallPrefix
+ for _, name := range calls {
+ fmt.Fprintf(buf, "#ifndef %v%v\n", prefix, name)
+ fmt.Fprintf(buf, "#define %v%v %v\n", prefix, name, ctx.calls[name])
+ fmt.Fprintf(buf, "#endif\n")
}
if ctx.target.OS == "linux" && ctx.target.PtrSize == 4 {
// This is a dirty hack.
// On 32-bit linux mmap translated to old_mmap syscall which has a different signature.
// mmap2 has the right signature. syz-extract translates mmap to mmap2, do the same here.
- ctx.printf("#undef __NR_mmap\n")
- ctx.printf("#define __NR_mmap __NR_mmap2\n")
+ fmt.Fprintf(buf, "#undef __NR_mmap\n")
+ fmt.Fprintf(buf, "#define __NR_mmap __NR_mmap2\n")
}
- ctx.printf("\n")
+ return buf.String()
}
func (ctx *context) generateProgCalls(p *prog.Prog) ([]string, []uint64, error) {
@@ -332,7 +244,7 @@ func (ctx *context) generateCalls(p prog.ExecProg) ([]string, []uint64) {
fmt.Fprintf(w, "\t\tr[%v] = res;\n", call.Index)
}
for _, copyout := range call.Copyout {
- fmt.Fprintf(w, "\t\tNONFAILING(r[%v] = *(uint%v_t*)0x%x);\n",
+ fmt.Fprintf(w, "\t\tNONFAILING(r[%v] = *(uint%v*)0x%x);\n",
copyout.Index, copyout.Size*8, copyout.Addr)
}
if copyoutMultiple {
@@ -350,18 +262,18 @@ func (ctx *context) generateCsumInet(w *bytes.Buffer, addr uint64, arg prog.Exec
for i, chunk := range arg.Chunks {
switch chunk.Kind {
case prog.ExecArgCsumChunkData:
- fmt.Fprintf(w, "\tNONFAILING(csum_inet_update(&csum_%d, (const uint8_t*)0x%x, %d));\n",
+ fmt.Fprintf(w, "\tNONFAILING(csum_inet_update(&csum_%d, (const uint8*)0x%x, %d));\n",
csumSeq, chunk.Value, chunk.Size)
case prog.ExecArgCsumChunkConst:
- fmt.Fprintf(w, "\tuint%d_t csum_%d_chunk_%d = 0x%x;\n",
+ fmt.Fprintf(w, "\tuint%d csum_%d_chunk_%d = 0x%x;\n",
chunk.Size*8, csumSeq, i, chunk.Value)
- fmt.Fprintf(w, "\tcsum_inet_update(&csum_%d, (const uint8_t*)&csum_%d_chunk_%d, %d);\n",
+ fmt.Fprintf(w, "\tcsum_inet_update(&csum_%d, (const uint8*)&csum_%d_chunk_%d, %d);\n",
csumSeq, csumSeq, i, chunk.Size)
default:
panic(fmt.Sprintf("unknown checksum chunk kind %v", chunk.Kind))
}
}
- fmt.Fprintf(w, "\tNONFAILING(*(uint16_t*)0x%x = csum_inet_digest(&csum_%d));\n",
+ fmt.Fprintf(w, "\tNONFAILING(*(uint16*)0x%x = csum_inet_digest(&csum_%d));\n",
addr, csumSeq)
}
@@ -374,7 +286,7 @@ func (ctx *context) copyin(w *bytes.Buffer, csumSeq *int, copyin prog.ExecCopyin
if arg.Format != prog.FormatNative && arg.Format != prog.FormatBigEndian {
panic("bitfield+string format")
}
- fmt.Fprintf(w, "\tNONFAILING(STORE_BY_BITMASK(uint%v_t, 0x%x, %v, %v, %v));\n",
+ fmt.Fprintf(w, "\tNONFAILING(STORE_BY_BITMASK(uint%v, 0x%x, %v, %v, %v));\n",
arg.Size*8, copyin.Addr, ctx.constArgToStr(arg),
arg.BitfieldOffset, arg.BitfieldLength)
}
@@ -399,7 +311,7 @@ func (ctx *context) copyin(w *bytes.Buffer, csumSeq *int, copyin prog.ExecCopyin
func (ctx *context) copyinVal(w *bytes.Buffer, addr, size uint64, val string, bf prog.BinaryFormat) {
switch bf {
case prog.FormatNative, prog.FormatBigEndian:
- fmt.Fprintf(w, "\tNONFAILING(*(uint%v_t*)0x%x = %v);\n", size*8, addr, val)
+ fmt.Fprintf(w, "\tNONFAILING(*(uint%v*)0x%x = %v);\n", size*8, addr, val)
case prog.FormatStrDec:
if size != 20 {
panic("bad strdec size")
@@ -506,6 +418,8 @@ func (ctx *context) hoistIncludes(result []byte) []byte {
func (ctx *context) removeEmptyLines(result []byte) []byte {
for {
newResult := bytes.Replace(result, []byte{'\n', '\n', '\n'}, []byte{'\n', '\n'}, -1)
+ newResult = bytes.Replace(newResult, []byte{'\n', '\n', '\t'}, []byte{'\n', '\t'}, -1)
+ newResult = bytes.Replace(newResult, []byte{'\n', '\n', ' '}, []byte{'\n', ' '}, -1)
if len(newResult) == len(result) {
return result
}
diff --git a/pkg/csource/generated.go b/pkg/csource/generated.go
index 9c9241010..7cd6f8777 100644
--- a/pkg/csource/generated.go
+++ b/pkg/csource/generated.go
@@ -25,6 +25,11 @@ NORETURN void doexit(int status)
}
#endif
+#if SYZ_EXECUTOR || SYZ_PROCS || SYZ_REPEAT && SYZ_ENABLE_CGROUPS || \
+ __NR_syz_mount_image || __NR_syz_read_part_table
+unsigned long long procid;
+#endif
+
#if !GOOS_fuchsia && !GOOS_windows
#if SYZ_EXECUTOR || SYZ_HANDLE_SEGV
#include <setjmp.h>
@@ -328,9 +333,8 @@ static uint16 csum_inet_digest(struct csum_inet* csum)
#if GOOS_akaros
+#include <ros/syscall.h>
#include <stdlib.h>
-#include <sys/mman.h>
-#include <sys/syscall.h>
#include <unistd.h>
#if SYZ_EXECUTOR || SYZ_SANDBOX_NONE
@@ -360,12 +364,10 @@ void child()
}
#endif
+#if SYZ_EXECUTOR
#define do_sandbox_setuid() 0
#define do_sandbox_namespace() 0
-#define setup_loop()
-#define reset_loop()
-#define setup_test()
-#define reset_test()
+#endif
#elif GOOS_freebsd || GOOS_netbsd
@@ -380,12 +382,10 @@ static int do_sandbox_none(void)
}
#endif
+#if SYZ_EXECUTOR
#define do_sandbox_setuid() 0
#define do_sandbox_namespace() 0
-#define setup_loop()
-#define reset_loop()
-#define setup_test()
-#define reset_test()
+#endif
#elif GOOS_fuchsia
@@ -622,8 +622,11 @@ static int do_sandbox_none(void)
}
#endif
+#if SYZ_EXECUTOR
#define do_sandbox_setuid() 0
#define do_sandbox_namespace() 0
+#endif
+
#define setup_loop()
#define reset_loop()
#define setup_test()
@@ -632,7 +635,6 @@ static int do_sandbox_none(void)
#include <stdlib.h>
-#include <sys/mount.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
@@ -1221,8 +1223,6 @@ static long syz_genetlink_get_family_id(long name)
#include <sys/stat.h>
#include <sys/types.h>
-extern unsigned long long procid;
-
struct fs_image_segment {
void* data;
uintptr_t size;
@@ -1335,6 +1335,9 @@ error:
#endif
#if SYZ_EXECUTOR || __NR_syz_mount_image
+#include <string.h>
+#include <sys/mount.h>
+
static long syz_mount_image(long fsarg, long dir, unsigned long size, unsigned long nsegs, long segments, long flags, long optsarg)
{
char loopname[64], fs[32], opts[256];
@@ -2399,6 +2402,7 @@ static long syz_kvm_setup_cpu(long a0, long a1, long a2, long a3, long a4, long
#include <fcntl.h>
#include <stdarg.h>
#include <stdbool.h>
+#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -2430,6 +2434,7 @@ static bool write_file(const char* file, const char* what, ...)
#include <errno.h>
#include <linux/net.h>
#include <netinet/in.h>
+#include <string.h>
#include <sys/socket.h>
@@ -3067,6 +3072,7 @@ static int do_sandbox_setuid(void)
#include <linux/capability.h>
#include <sched.h>
#include <sys/mman.h>
+#include <sys/mount.h>
static int real_uid;
static int real_gid;
@@ -3189,6 +3195,8 @@ static int do_sandbox_namespace(void)
#if SYZ_EXECUTOR || SYZ_REPEAT && SYZ_USE_TMP_DIR
#include <dirent.h>
#include <errno.h>
+#include <string.h>
+#include <sys/mount.h>
static void remove_dir(const char* dir)
{
@@ -3268,6 +3276,7 @@ retry:
#if SYZ_EXECUTOR || SYZ_FAULT_INJECTION
#include <fcntl.h>
+#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -3302,16 +3311,14 @@ static int fault_injected(int fail_fd)
}
#endif
-#if SYZ_EXECUTOR || SYZ_REPEAT
+#if SYZ_EXECUTOR || SYZ_REPEAT && SYZ_ENABLE_CGROUPS
#include <fcntl.h>
#include <sys/ioctl.h>
-#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
-extern unsigned long long procid;
-
+#define SYZ_HAVE_SETUP_LOOP 1
static void setup_loop()
{
#if SYZ_ENABLE_CGROUPS
@@ -3344,7 +3351,10 @@ static void setup_loop()
}
#endif
}
+#endif
+#if SYZ_EXECUTOR || SYZ_REPEAT && (SYZ_RESET_NET_NAMESPACE || __NR_syz_mount_image || __NR_syz_read_part_table)
+#define SYZ_HAVE_RESET_LOOP 1
static void reset_loop()
{
#if SYZ_EXECUTOR || __NR_syz_mount_image || __NR_syz_read_part_table
@@ -3360,7 +3370,12 @@ static void reset_loop()
reset_net_namespace();
#endif
}
+#endif
+#if SYZ_EXECUTOR || SYZ_REPEAT
+#include <sys/prctl.h>
+
+#define SYZ_HAVE_SETUP_TEST 1
static void setup_test()
{
prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
@@ -3385,6 +3400,7 @@ static void setup_test()
#endif
}
+#define SYZ_HAVE_RESET_TEST 1
static void reset_test()
{
int fd;
@@ -3414,12 +3430,10 @@ static int do_sandbox_none(void)
}
#endif
+#if SYZ_EXECUTOR
#define do_sandbox_setuid() 0
#define do_sandbox_namespace() 0
-#define setup_loop()
-#define reset_loop()
-#define setup_test()
-#define reset_test()
+#endif
#elif GOOS_windows
@@ -3523,10 +3537,19 @@ static int event_timedwait(event_t* ev, uint64 timeout_ms)
}
#endif
-#define setup_loop()
-#define reset_loop()
-#define setup_test()
-#define reset_test()
+#if SYZ_EXECUTOR || SYZ_SANDBOX_NONE
+static void loop();
+static int do_sandbox_none(void)
+{
+ loop();
+ doexit(0);
+}
+#endif
+
+#if SYZ_EXECUTOR
+#define do_sandbox_setuid() 0
+#define do_sandbox_namespace() 0
+#endif
#elif GOOS_test
@@ -3549,12 +3572,10 @@ static int do_sandbox_none(void)
}
#endif
+#if SYZ_EXECUTOR
#define do_sandbox_setuid() 0
#define do_sandbox_namespace() 0
-#define setup_loop()
-#define reset_loop()
-#define setup_test()
-#define reset_test()
+#endif
#else
#error "unknown OS"
#endif
@@ -3568,9 +3589,6 @@ struct thread_t {
static struct thread_t threads[16];
static void execute_call(int call);
static int running;
-#if SYZ_COLLIDE
-static int collide;
-#endif
static void* thr(void* arg)
{
@@ -3585,11 +3603,22 @@ static void* thr(void* arg)
return 0;
}
-static void execute(int num_calls)
+#if SYZ_REPEAT
+static void execute_one()
+#else
+static void loop()
+#endif
{
+#if SYZ_REPRO
+ if (write(1, "executing program\n", sizeof("executing program\n") - 1)) {
+ }
+#endif
int call, thread;
- running = 0;
- for (call = 0; call < num_calls; call++) {
+#if SYZ_COLLIDE
+ int collide = 0;
+again:
+#endif
+ for (call = 0; call < [[NUM_CALLS]]; call++) {
for (thread = 0; thread < sizeof(threads) / sizeof(threads[0]); thread++) {
struct thread_t* th = &threads[thread];
if (!th->created) {
@@ -3611,10 +3640,16 @@ static void execute(int num_calls)
#endif
event_timedwait(&th->done, 25);
if (__atomic_load_n(&running, __ATOMIC_RELAXED))
- sleep_ms((call == num_calls - 1) ? 10 : 2);
+ sleep_ms((call == [[NUM_CALLS]] - 1) ? 10 : 2);
break;
}
}
+#if SYZ_COLLIDE
+ if (!collide) {
+ collide = 1;
+ goto again;
+ }
+#endif
}
#endif
@@ -3637,7 +3672,9 @@ static void reply_handshake();
static void loop()
{
+#if SYZ_HAVE_SETUP_LOOP
setup_loop();
+#endif
#if SYZ_EXECUTOR
reply_handshake();
#endif
@@ -3654,7 +3691,9 @@ static void loop()
if (mkdir(cwdbuf, 0777))
fail("failed to mkdir");
#endif
+#if SYZ_HAVE_RESET_LOOP
reset_loop();
+#endif
#if SYZ_EXECUTOR
receive_execute();
#endif
@@ -3662,7 +3701,9 @@ static void loop()
if (pid < 0)
fail("clone failed");
if (pid == 0) {
+#if SYZ_HAVE_SETUP_TEST
setup_test();
+#endif
#if SYZ_EXECUTOR || SYZ_USE_TMP_DIR
if (chdir(cwdbuf))
fail("failed to chdir");
@@ -3684,7 +3725,9 @@ static void loop()
#endif
execute_one();
debug("worker exiting\n");
+#if SYZ_HAVE_RESET_TEST
reset_test();
+#endif
doexit(0);
#endif
}
@@ -3746,4 +3789,61 @@ static void loop()
}
#endif
#endif
+
+#if !SYZ_EXECUTOR
+[[SYSCALL_DEFINES]]
+
+[[RESULTS]]
+
+#if SYZ_THREADED || SYZ_REPEAT || SYZ_SANDBOX_NONE || SYZ_SANDBOX_SETUID || SYZ_SANDBOX_NAMESPACE
+#if SYZ_THREADED
+void
+execute_call(int call)
+#elif SYZ_REPEAT
+void
+execute_one()
+#else
+void
+loop()
+#endif
+{
+ [[SYSCALLS]]
+}
+#endif
+
+#if GOOS_akaros && SYZ_REPEAT
+#include <string.h>
+
+int main(int argc, char** argv)
+{
+ [[MMAP_DATA]]
+
+ program_name = argv[0];
+ if (argc == 2 && strcmp(argv[1], "child") == 0)
+ child();
+#else
+int
+main()
+{
+ [[MMAP_DATA]]
+#endif
+#if SYZ_HANDLE_SEGV
+ install_segv_handler();
+#endif
+#if SYZ_PROCS
+ for (procid = 0; procid < [[PROCS]]; procid++) {
+ if (fork() == 0) {
+#endif
+#if SYZ_USE_TMP_DIR
+ use_temporary_dir();
+#endif
+ [[SANDBOX_FUNC]]
+#if SYZ_PROCS
+ }
+ }
+ sleep(1000000);
+#endif
+ return 0;
+}
+#endif
`