aboutsummaryrefslogtreecommitdiffstats
path: root/csource
diff options
context:
space:
mode:
Diffstat (limited to 'csource')
-rw-r--r--csource/common.go148
-rw-r--r--csource/csource.go30
2 files changed, 165 insertions, 13 deletions
diff --git a/csource/common.go b/csource/common.go
new file mode 100644
index 000000000..46dfca8ce
--- /dev/null
+++ b/csource/common.go
@@ -0,0 +1,148 @@
+// AUTOGENERATED FROM executor/common.h
+package csource
+
+var commonHeader = `
+
+#include <fcntl.h>
+#include <pthread.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+__thread int skip_segv;
+__thread jmp_buf segv_env;
+
+static void segv_handler(int sig, siginfo_t* info, void* uctx)
+{
+ if (__atomic_load_n(&skip_segv, __ATOMIC_RELAXED))
+ _longjmp(segv_env, 1);
+ exit(sig);
+}
+
+static void install_segv_handler()
+{
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_sigaction = segv_handler;
+ sa.sa_flags = SA_NODEFER | SA_SIGINFO;
+ sigaction(SIGSEGV, &sa, NULL);
+ 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); \
+ }
+
+static uintptr_t syz_open_dev(uintptr_t a0, uintptr_t a1, uintptr_t a2)
+{
+ if (a0 == 0xc || a0 == 0xb) {
+ char buf[128];
+ sprintf(buf, "/dev/%s/%d:%d", a0 == 0xc ? "char" : "block", (uint8_t)a1, (uint8_t)a2);
+ return open(buf, O_RDWR, 0);
+ } else {
+ char buf[1024];
+ char* hash;
+ strncpy(buf, (char*)a0, sizeof(buf));
+ buf[sizeof(buf) - 1] = 0;
+ while ((hash = strchr(buf, '#'))) {
+ *hash = '0' + (char)(a1 % 10);
+ a1 /= 10;
+ }
+ return open(buf, a2, 0);
+ }
+}
+
+static uintptr_t syz_open_pts(uintptr_t a0, uintptr_t a1)
+{
+ int ptyno = 0;
+ if (ioctl(a0, TIOCGPTN, &ptyno))
+ return -1;
+ char buf[128];
+ sprintf(buf, "/dev/pts/%d", ptyno);
+ return open(buf, a1, 0);
+}
+
+static uintptr_t syz_fuse_mount(uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5)
+{
+ uint64_t target = a0;
+ uint64_t mode = a1;
+ uint64_t uid = a2;
+ uint64_t gid = a3;
+ uint64_t maxread = a4;
+ uint64_t flags = a5;
+
+ int fd = open("/dev/fuse", O_RDWR);
+ if (fd == -1)
+ return fd;
+ char buf[1024];
+ sprintf(buf, "fd=%d,user_id=%ld,group_id=%ld,rootmode=0%o", fd, (long)uid, (long)gid, (unsigned)mode & ~3u);
+ if (maxread != 0)
+ sprintf(buf + strlen(buf), ",max_read=%ld", (long)maxread);
+ if (mode & 1)
+ strcat(buf, ",default_permissions");
+ if (mode & 2)
+ strcat(buf, ",allow_other");
+ syscall(SYS_mount, "", target, "fuse", flags, buf);
+ return fd;
+}
+
+static uintptr_t syz_fuseblk_mount(uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7)
+{
+ uint64_t target = a0;
+ uint64_t blkdev = a1;
+ uint64_t mode = a2;
+ uint64_t uid = a3;
+ uint64_t gid = a4;
+ uint64_t maxread = a5;
+ uint64_t blksize = a6;
+ uint64_t flags = a7;
+
+ int fd = open("/dev/fuse", O_RDWR);
+ if (fd == -1)
+ return fd;
+ if (syscall(SYS_mknodat, AT_FDCWD, blkdev, S_IFBLK, makedev(7, 199)))
+ return fd;
+ char buf[256];
+ sprintf(buf, "fd=%d,user_id=%ld,group_id=%ld,rootmode=0%o", fd, (long)uid, (long)gid, (unsigned)mode & ~3u);
+ if (maxread != 0)
+ sprintf(buf + strlen(buf), ",max_read=%ld", (long)maxread);
+ if (blksize != 0)
+ sprintf(buf + strlen(buf), ",blksize=%ld", (long)blksize);
+ if (mode & 1)
+ strcat(buf, ",default_permissions");
+ if (mode & 2)
+ strcat(buf, ",allow_other");
+ syscall(SYS_mount, blkdev, target, "fuseblk", flags, buf);
+ return fd;
+}
+
+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) {
+ default:
+ return syscall(nr, a0, a1, a2, a3, a4, a5);
+ case __NR_syz_open_dev:
+ return syz_open_dev(a0, a1, a2);
+ case __NR_syz_open_pts:
+ return syz_open_pts(a0, a1);
+ case __NR_syz_fuse_mount:
+ return syz_fuse_mount(a0, a1, a2, a3, a4, a5);
+ case __NR_syz_fuseblk_mount:
+ return syz_fuseblk_mount(a0, a1, a2, a3, a4, a5, a6, a7);
+ }
+}
+`
diff --git a/csource/csource.go b/csource/csource.go
index 214483c5d..28be9e22a 100644
--- a/csource/csource.go
+++ b/csource/csource.go
@@ -1,7 +1,7 @@
// Copyright 2015 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
-//go:generate bash -c "echo -e '// AUTOGENERATED FROM executor/common.h\npackage csource\nvar commonHeader = `' > common.go; cat ../executor/common.h | grep -v // >> common.go; echo '`' >> common.go"
+//go:generate bash -c "echo -e '// AUTOGENERATED FROM executor/common.h\npackage csource\nvar commonHeader = `' > common.go; cat ../executor/common.h | egrep -v '^[ ]*//' | sed 's#[ ]*//.*##g' >> common.go; echo '`' >> common.go"
package csource
@@ -27,23 +27,27 @@ func Write(p *prog.Prog, opts Options) []byte {
exec := p.SerializeForExec()
w := new(bytes.Buffer)
- fmt.Fprint(w, "// autogenerated by syzkaller (http://github.com/google/syzkaller)\n")
- fmt.Fprint(w, commonHeader)
- fmt.Fprint(w, "\n")
+ fmt.Fprint(w, "// autogenerated by syzkaller (http://github.com/google/syzkaller)\n\n")
- handled := make(map[string]bool)
+ handled := make(map[string]int)
for _, c := range p.Calls {
- name := c.Meta.CallName
- if handled[name] {
- continue
+ handled[c.Meta.CallName] = c.Meta.NR
+ }
+ for _, c := range sys.Calls {
+ if strings.HasPrefix(c.CallName, "syz_") {
+ handled[c.CallName] = c.NR
}
- handled[name] = true
- fmt.Fprintf(w, "#ifndef SYS_%v\n", name)
- fmt.Fprintf(w, "#define SYS_%v %v\n", name, c.Meta.NR)
+ }
+ for name, nr := range handled {
+ fmt.Fprintf(w, "#ifndef __NR_%v\n", name)
+ fmt.Fprintf(w, "#define __NR_%v %v\n", name, nr)
fmt.Fprintf(w, "#endif\n")
}
fmt.Fprintf(w, "\n")
+ fmt.Fprint(w, commonHeader)
+ fmt.Fprint(w, "\n")
+
calls, nvar := generateCalls(exec)
fmt.Fprintf(w, "long r[%v];\n", nvar)
@@ -166,7 +170,7 @@ loop:
// Normal syscall.
newCall()
meta := sys.Calls[instr]
- fmt.Fprintf(w, "\tr[%v] = syscall(SYS_%v", n, meta.CallName)
+ fmt.Fprintf(w, "\tr[%v] = execute_syscall(__NR_%v", n, meta.CallName)
nargs := read()
for i := uintptr(0); i < nargs; i++ {
typ := read()
@@ -181,7 +185,7 @@ loop:
panic("unknown arg type")
}
}
- for i := nargs; i < 6; i++ {
+ for i := nargs; i < 9; i++ {
fmt.Fprintf(w, ", 0")
}
fmt.Fprintf(w, ");\n")