aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Steuck <blackgnezdo@gmail.com>2018-11-17 15:42:37 -0800
committerDmitry Vyukov <dvyukov@google.com>2018-11-17 15:42:37 -0800
commit538a10560010f93f22b0a8912dbd221d077deaa4 (patch)
tree48c09d26e7bc9f6e1fadf7145b2dc43dda238d46
parentadf636a83bd411d805aa74d07d03933ae9d08eb3 (diff)
executor: OpenBSD network package injection
Squash of: * Doc typo * Ported some tun related functions. * Copy vnet.txt from linux to openbsd. * Simplified syz_emit_ethernet and stubbed out vnet.txt. * Undo clang-format header sorting: headers are order sensitive. * Uniquify tap devices by pid. * clang-format off for includes * Happier clang-format. * Partially revert "Uniquify tap devices by pid." Just rely on procid magic instead of getting it from a flag.
-rw-r--r--docs/linux/external_fuzzing_network.md2
-rw-r--r--executor/common_bsd.h239
-rw-r--r--executor/defs.h2
-rw-r--r--executor/syscalls.h3
-rw-r--r--pkg/csource/generated.go220
-rw-r--r--sys/openbsd/gen/amd64.go21
-rw-r--r--sys/openbsd/vnet.txt20
7 files changed, 491 insertions, 16 deletions
diff --git a/docs/linux/external_fuzzing_network.md b/docs/linux/external_fuzzing_network.md
index f080692b1..03463f876 100644
--- a/docs/linux/external_fuzzing_network.md
+++ b/docs/linux/external_fuzzing_network.md
@@ -23,7 +23,7 @@ Since many network protocols require checksum fields to be embedded into packets
There's a `csum` type, which right now supports two different kinds of checksumming:
[the Internet checksum](https://tools.ietf.org/html/rfc1071): `csum[parent, inet, int16be]`,
and TCP-like pseudo header checksum: `csum[tcp_packet, pseudo, IPPROTO_TCP, int16be]`.
-The checksums are computed and embedded right before emitting a packet though the virtual interface.
+The checksums are computed and embedded right before emitting a packet through the virtual interface.
There's also a nice feature: when syzkaller generates a C reproducer, it generates code to compute checksums in runtime as well.
By using `syz_emit_ethernet` and `syz_extract_tcp_res` the following syzkaller program is able to establish a TCP connection over IPv4:
diff --git a/executor/common_bsd.h b/executor/common_bsd.h
index 63ae6c1d1..e09437353 100644
--- a/executor/common_bsd.h
+++ b/executor/common_bsd.h
@@ -5,14 +5,54 @@
#include <unistd.h>
-#if SYZ_EXECUTOR || SYZ_SANDBOX_NONE
-static void loop();
-static int do_sandbox_none(void)
+#include <stdarg.h>
+#include <stdbool.h>
+#include <string.h>
+
+static void vsnprintf_check(char* str, size_t size, const char* format, va_list args)
{
- loop();
- return 0;
+ int rv;
+
+ rv = vsnprintf(str, size, format, args);
+ if (rv < 0)
+ fail("vsnprintf failed");
+ if ((size_t)rv >= size)
+ fail("vsnprintf: string '%s...' doesn't fit into buffer", str);
+}
+
+static void snprintf_check(char* str, size_t size, const char* format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ vsnprintf_check(str, size, format, args);
+ va_end(args);
+}
+
+#define COMMAND_MAX_LEN 128
+#define PATH_PREFIX "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin "
+#define PATH_PREFIX_LEN (sizeof(PATH_PREFIX) - 1)
+
+static void execute_command(bool panic, const char* format, ...)
+{
+ va_list args;
+ char command[PATH_PREFIX_LEN + COMMAND_MAX_LEN];
+ int rv;
+
+ va_start(args, format);
+ // Executor process does not have any env, including PATH.
+ // On some distributions, system/shell adds a minimal PATH, on some it does not.
+ // Set own standard PATH to make it work across distributions.
+ memcpy(command, PATH_PREFIX, PATH_PREFIX_LEN);
+ vsnprintf_check(command + PATH_PREFIX_LEN, COMMAND_MAX_LEN, format, args);
+ va_end(args);
+ rv = system(command);
+ if (rv) {
+ if (panic)
+ fail("command '%s' failed: %d", &command[0], rv);
+ debug("command '%s': %d\n", &command[0], rv);
+ }
}
-#endif
#if GOOS_openbsd
@@ -26,7 +66,7 @@ static int do_sandbox_none(void)
#else
// Needed when compiling on Linux.
#include <pty.h>
-#endif
+#endif // defined(__OpenBSD__)
static uintptr_t syz_open_pts(void)
{
@@ -41,6 +81,191 @@ static uintptr_t syz_open_pts(void)
return slave;
}
+#endif // SYZ_EXECUTOR || __NR_syz_open_pts
+
+#if SYZ_EXECUTOR || SYZ_TUN_ENABLE
+
+#include <fcntl.h>
+#include <net/if_tun.h>
+#include <sys/types.h>
+
+static int tunfd = -1;
+
+// We just need this to be large enough to hold headers that we parse (ethernet/ip/tcp).
+// Rest of the packet (if any) will be silently truncated which is fine.
+#define SYZ_TUN_MAX_PACKET_SIZE 1000
+
+// Maximum number of tun devices in the default install.
+#define MAX_TUN 4
+
+// All patterns are non-expanding given values < MAX_TUN.
+#define TUN_IFACE "tap%d"
+#define TUN_DEVICE "/dev/tap%d"
+
+#define LOCAL_IPV4 "172.20.%d.170"
+#define LOCAL_IPV6 "fe80::%02hxaa"
+
+static void initialize_tun(int tun_id)
+{
+#if SYZ_EXECUTOR
+ if (!flag_enable_tun)
+ return;
+#endif // SYZ_EXECUTOR
+
+ if (tun_id < 0 || tun_id >= MAX_TUN) {
+ fail("tun_id out of range %d\n", tun_id);
+ }
+
+ char tun_device[sizeof(TUN_DEVICE)];
+ snprintf_check(tun_device, sizeof(tun_device), TUN_DEVICE, tun_id);
+
+ tunfd = open(tun_device, O_RDWR | O_NONBLOCK);
+ if (tunfd == -1) {
+#if SYZ_EXECUTOR
+ fail("tun: can't open %s\n", tun_device);
+#else
+ printf("tun: can't open %s: errno=%d\n", tun_device, errno);
+ return;
+#endif // SYZ_EXECUTOR
+ }
+ // Remap tun onto higher fd number to hide it from fuzzer and to keep
+ // fd numbers stable regardless of whether tun is opened or not (also see kMaxFd).
+ const int kTunFd = 240;
+ if (dup2(tunfd, kTunFd) < 0)
+ fail("dup2(tunfd, kTunFd) failed");
+ close(tunfd);
+ tunfd = kTunFd;
+
+ char tun_iface[sizeof(TUN_IFACE)];
+ snprintf_check(tun_iface, sizeof(tun_iface), TUN_IFACE, tun_id);
+
+ char local_ipv4[sizeof(LOCAL_IPV4)];
+ snprintf_check(local_ipv4, sizeof(local_ipv4), LOCAL_IPV4, tun_id);
+ execute_command(1, "ifconfig %s inet %s", tun_iface, local_ipv4);
+
+ char local_ipv6[sizeof(LOCAL_IPV6)];
+ snprintf_check(local_ipv6, sizeof(local_ipv6), LOCAL_IPV6, tun_id);
+ execute_command(1, "ifconfig %s inet6 %s", tun_iface, local_ipv6);
+}
+
+#endif // SYZ_EXECUTOR || SYZ_TUN_ENABLE
+
+#if SYZ_EXECUTOR || __NR_syz_emit_ethernet && SYZ_TUN_ENABLE
+#include <stdbool.h>
+#include <sys/uio.h>
+
+static long syz_emit_ethernet(long a0, long a1)
+{
+ // syz_emit_ethernet(len len[packet], packet ptr[in, eth_packet])
+ if (tunfd < 0)
+ return (uintptr_t)-1;
+
+ size_t length = a0;
+ const char* data = (char*)a1;
+ debug_dump_data(data, length);
+
+ return write(tunfd, data, length);
+}
+#endif
+
+#if SYZ_EXECUTOR || SYZ_TUN_ENABLE && (__NR_syz_extract_tcp_res || SYZ_REPEAT)
+#include <errno.h>
+
+static int read_tun(char* data, int size)
+{
+ if (tunfd < 0)
+ return -1;
+
+ int rv = read(tunfd, data, size);
+ if (rv < 0) {
+ if (errno == EAGAIN)
+ return -1;
+ fail("tun: read failed with %d", rv);
+ }
+ return rv;
+}
#endif
+#if SYZ_EXECUTOR || __NR_syz_extract_tcp_res && SYZ_TUN_ENABLE
+
+struct tcp_resources {
+ uint32 seq;
+ uint32 ack;
+};
+
+#include <net/ethertypes.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip6.h>
+#include <netinet/tcp.h>
+
+// Include order matters, empty line prevent re-sorting.
+#include <netinet/if_ether.h>
+
+static long syz_extract_tcp_res(long a0, long a1, long a2)
+{
+ // syz_extract_tcp_res(res ptr[out, tcp_resources], seq_inc int32, ack_inc int32)
+
+ if (tunfd < 0)
+ return (uintptr_t)-1;
+
+ char data[SYZ_TUN_MAX_PACKET_SIZE];
+ int rv = read_tun(&data[0], sizeof(data));
+ if (rv == -1)
+ return (uintptr_t)-1;
+ size_t length = rv;
+ debug_dump_data(data, length);
+
+ struct tcphdr* tcphdr;
+
+ if (length < sizeof(struct ether_header))
+ return (uintptr_t)-1;
+ struct ether_header* ethhdr = (struct ether_header*)&data[0];
+
+ if (ethhdr->ether_type == htons(ETHERTYPE_IP)) {
+ if (length < sizeof(struct ether_header) + sizeof(struct ip))
+ return (uintptr_t)-1;
+ struct ip* iphdr = (struct ip*)&data[sizeof(struct ether_header)];
+ if (iphdr->ip_p != IPPROTO_TCP)
+ return (uintptr_t)-1;
+ if (length < sizeof(struct ether_header) + iphdr->ip_hl * 4 + sizeof(struct tcphdr))
+ return (uintptr_t)-1;
+ tcphdr = (struct tcphdr*)&data[sizeof(struct ether_header) + iphdr->ip_hl * 4];
+ } else {
+ if (length < sizeof(struct ether_header) + sizeof(struct ip6_hdr))
+ return (uintptr_t)-1;
+ struct ip6_hdr* ipv6hdr = (struct ip6_hdr*)&data[sizeof(struct ether_header)];
+ // TODO: parse and skip extension headers.
+ if (ipv6hdr->ip6_nxt != IPPROTO_TCP)
+ return (uintptr_t)-1;
+ if (length < sizeof(struct ether_header) + sizeof(struct ip6_hdr) + sizeof(struct tcphdr))
+ return (uintptr_t)-1;
+ tcphdr = (struct tcphdr*)&data[sizeof(struct ether_header) + sizeof(struct ip6_hdr)];
+ }
+
+ struct tcp_resources* res = (struct tcp_resources*)a0;
+ NONFAILING(res->seq = htonl((ntohl(tcphdr->th_seq) + (uint32)a1)));
+ NONFAILING(res->ack = htonl((ntohl(tcphdr->th_ack) + (uint32)a2)));
+
+ debug("extracted seq: %08x\n", res->seq);
+ debug("extracted ack: %08x\n", res->ack);
+
+ return 0;
+}
+#endif
+
+#if SYZ_EXECUTOR || SYZ_SANDBOX_NONE
+static void loop();
+static int do_sandbox_none(void)
+{
+#if SYZ_EXECUTOR || SYZ_TUN_ENABLE
+ initialize_tun(procid);
#endif
+ loop();
+ return 0;
+}
+#endif // SYZ_EXECUTOR || SYZ_SANDBOX_NONE
+
+#endif // GOOS_openbsd
diff --git a/executor/defs.h b/executor/defs.h
index 72ae20794..1b6da6208 100644
--- a/executor/defs.h
+++ b/executor/defs.h
@@ -130,7 +130,7 @@
#if GOARCH_amd64
#define GOARCH "amd64"
-#define SYZ_REVISION "df30b58093a18d87ed6803bfe65ec9af86f721a3"
+#define SYZ_REVISION "05e6185f1ea57bbe311ffe3829b1cca890f472fc"
#define SYZ_EXECUTOR_USES_FORK_SERVER 1
#define SYZ_EXECUTOR_USES_SHMEM 1
#define SYZ_PAGE_SIZE 4096
diff --git a/executor/syscalls.h b/executor/syscalls.h
index 9f01c99ff..fb0ea2d1c 100644
--- a/executor/syscalls.h
+++ b/executor/syscalls.h
@@ -12933,7 +12933,10 @@ const call_t syscalls[] = {
{"symlink", 57},
{"symlinkat", 324},
{"sync", 36},
+ {"syz_emit_ethernet", 0, (syscall_t)syz_emit_ethernet},
{"syz_execute_func", 0, (syscall_t)syz_execute_func},
+ {"syz_extract_tcp_res", 0, (syscall_t)syz_extract_tcp_res},
+ {"syz_extract_tcp_res$synack", 0, (syscall_t)syz_extract_tcp_res},
{"syz_open_pts", 0, (syscall_t)syz_open_pts},
{"truncate", 200},
{"unlink", 10},
diff --git a/pkg/csource/generated.go b/pkg/csource/generated.go
index d467fe621..a5124979b 100644
--- a/pkg/csource/generated.go
+++ b/pkg/csource/generated.go
@@ -398,14 +398,51 @@ void child()
#include <unistd.h>
-#if SYZ_EXECUTOR || SYZ_SANDBOX_NONE
-static void loop();
-static int do_sandbox_none(void)
+#include <stdarg.h>
+#include <stdbool.h>
+#include <string.h>
+
+static void vsnprintf_check(char* str, size_t size, const char* format, va_list args)
{
- loop();
- return 0;
+ int rv;
+
+ rv = vsnprintf(str, size, format, args);
+ if (rv < 0)
+ fail("vsnprintf failed");
+ if ((size_t)rv >= size)
+ fail("vsnprintf: string '%s...' doesn't fit into buffer", str);
+}
+
+static void snprintf_check(char* str, size_t size, const char* format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ vsnprintf_check(str, size, format, args);
+ va_end(args);
+}
+
+#define COMMAND_MAX_LEN 128
+#define PATH_PREFIX "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin "
+#define PATH_PREFIX_LEN (sizeof(PATH_PREFIX) - 1)
+
+static void execute_command(bool panic, const char* format, ...)
+{
+ va_list args;
+ char command[PATH_PREFIX_LEN + COMMAND_MAX_LEN];
+ int rv;
+
+ va_start(args, format);
+ memcpy(command, PATH_PREFIX, PATH_PREFIX_LEN);
+ vsnprintf_check(command + PATH_PREFIX_LEN, COMMAND_MAX_LEN, format, args);
+ va_end(args);
+ rv = system(command);
+ if (rv) {
+ if (panic)
+ fail("command '%s' failed: %d", &command[0], rv);
+ debug("command '%s': %d\n", &command[0], rv);
+ }
}
-#endif
#if GOOS_openbsd
@@ -433,6 +470,177 @@ static uintptr_t syz_open_pts(void)
#endif
+#if SYZ_EXECUTOR || SYZ_TUN_ENABLE
+
+#include <fcntl.h>
+#include <net/if_tun.h>
+#include <sys/types.h>
+
+static int tunfd = -1;
+#define SYZ_TUN_MAX_PACKET_SIZE 1000
+#define MAX_TUN 4
+#define TUN_IFACE "tap%d"
+#define TUN_DEVICE "/dev/tap%d"
+
+#define LOCAL_IPV4 "172.20.%d.170"
+#define LOCAL_IPV6 "fe80::%02hxaa"
+
+static void initialize_tun(int tun_id)
+{
+#if SYZ_EXECUTOR
+ if (!flag_enable_tun)
+ return;
+#endif
+
+ if (tun_id < 0 || tun_id >= MAX_TUN) {
+ fail("tun_id out of range %d\n", tun_id);
+ }
+
+ char tun_device[sizeof(TUN_DEVICE)];
+ snprintf_check(tun_device, sizeof(tun_device), TUN_DEVICE, tun_id);
+
+ tunfd = open(tun_device, O_RDWR | O_NONBLOCK);
+ if (tunfd == -1) {
+#if SYZ_EXECUTOR
+ fail("tun: can't open %s\n", tun_device);
+#else
+ printf("tun: can't open %s: errno=%d\n", tun_device, errno);
+ return;
+#endif
+ }
+ const int kTunFd = 240;
+ if (dup2(tunfd, kTunFd) < 0)
+ fail("dup2(tunfd, kTunFd) failed");
+ close(tunfd);
+ tunfd = kTunFd;
+
+ char tun_iface[sizeof(TUN_IFACE)];
+ snprintf_check(tun_iface, sizeof(tun_iface), TUN_IFACE, tun_id);
+
+ char local_ipv4[sizeof(LOCAL_IPV4)];
+ snprintf_check(local_ipv4, sizeof(local_ipv4), LOCAL_IPV4, tun_id);
+ execute_command(1, "ifconfig %s inet %s", tun_iface, local_ipv4);
+
+ char local_ipv6[sizeof(LOCAL_IPV6)];
+ snprintf_check(local_ipv6, sizeof(local_ipv6), LOCAL_IPV6, tun_id);
+ execute_command(1, "ifconfig %s inet6 %s", tun_iface, local_ipv6);
+}
+
+#endif
+
+#if SYZ_EXECUTOR || __NR_syz_emit_ethernet && SYZ_TUN_ENABLE
+#include <stdbool.h>
+#include <sys/uio.h>
+
+static long syz_emit_ethernet(long a0, long a1)
+{
+ if (tunfd < 0)
+ return (uintptr_t)-1;
+
+ size_t length = a0;
+ const char* data = (char*)a1;
+ debug_dump_data(data, length);
+
+ return write(tunfd, data, length);
+}
+#endif
+
+#if SYZ_EXECUTOR || SYZ_TUN_ENABLE && (__NR_syz_extract_tcp_res || SYZ_REPEAT)
+#include <errno.h>
+
+static int read_tun(char* data, int size)
+{
+ if (tunfd < 0)
+ return -1;
+
+ int rv = read(tunfd, data, size);
+ if (rv < 0) {
+ if (errno == EAGAIN)
+ return -1;
+ fail("tun: read failed with %d", rv);
+ }
+ return rv;
+}
+#endif
+
+#if SYZ_EXECUTOR || __NR_syz_extract_tcp_res && SYZ_TUN_ENABLE
+
+struct tcp_resources {
+ uint32 seq;
+ uint32 ack;
+};
+
+#include <net/ethertypes.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip6.h>
+#include <netinet/tcp.h>
+#include <netinet/if_ether.h>
+
+static long syz_extract_tcp_res(long a0, long a1, long a2)
+{
+
+ if (tunfd < 0)
+ return (uintptr_t)-1;
+
+ char data[SYZ_TUN_MAX_PACKET_SIZE];
+ int rv = read_tun(&data[0], sizeof(data));
+ if (rv == -1)
+ return (uintptr_t)-1;
+ size_t length = rv;
+ debug_dump_data(data, length);
+
+ struct tcphdr* tcphdr;
+
+ if (length < sizeof(struct ether_header))
+ return (uintptr_t)-1;
+ struct ether_header* ethhdr = (struct ether_header*)&data[0];
+
+ if (ethhdr->ether_type == htons(ETHERTYPE_IP)) {
+ if (length < sizeof(struct ether_header) + sizeof(struct ip))
+ return (uintptr_t)-1;
+ struct ip* iphdr = (struct ip*)&data[sizeof(struct ether_header)];
+ if (iphdr->ip_p != IPPROTO_TCP)
+ return (uintptr_t)-1;
+ if (length < sizeof(struct ether_header) + iphdr->ip_hl * 4 + sizeof(struct tcphdr))
+ return (uintptr_t)-1;
+ tcphdr = (struct tcphdr*)&data[sizeof(struct ether_header) + iphdr->ip_hl * 4];
+ } else {
+ if (length < sizeof(struct ether_header) + sizeof(struct ip6_hdr))
+ return (uintptr_t)-1;
+ struct ip6_hdr* ipv6hdr = (struct ip6_hdr*)&data[sizeof(struct ether_header)];
+ if (ipv6hdr->ip6_nxt != IPPROTO_TCP)
+ return (uintptr_t)-1;
+ if (length < sizeof(struct ether_header) + sizeof(struct ip6_hdr) + sizeof(struct tcphdr))
+ return (uintptr_t)-1;
+ tcphdr = (struct tcphdr*)&data[sizeof(struct ether_header) + sizeof(struct ip6_hdr)];
+ }
+
+ struct tcp_resources* res = (struct tcp_resources*)a0;
+ NONFAILING(res->seq = htonl((ntohl(tcphdr->th_seq) + (uint32)a1)));
+ NONFAILING(res->ack = htonl((ntohl(tcphdr->th_ack) + (uint32)a2)));
+
+ debug("extracted seq: %08x\n", res->seq);
+ debug("extracted ack: %08x\n", res->ack);
+
+ return 0;
+}
+#endif
+
+#if SYZ_EXECUTOR || SYZ_SANDBOX_NONE
+static void loop();
+static int do_sandbox_none(void)
+{
+#if SYZ_EXECUTOR || SYZ_TUN_ENABLE
+ initialize_tun(procid);
+#endif
+ loop();
+ return 0;
+}
+#endif
+
#endif
#elif GOOS_fuchsia
diff --git a/sys/openbsd/gen/amd64.go b/sys/openbsd/gen/amd64.go
index 317e8f8e5..9b3b04f64 100644
--- a/sys/openbsd/gen/amd64.go
+++ b/sys/openbsd/gen/amd64.go
@@ -26,6 +26,7 @@ var resources_amd64 = []*ResourceDesc{
{Name: "sock_in", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"fd", "sock", "sock_in"}, Values: []uint64{18446744073709551615, 18446744073709551516}},
{Name: "sock_in6", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"fd", "sock", "sock_in6"}, Values: []uint64{18446744073709551615, 18446744073709551516}},
{Name: "sock_unix", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"fd", "sock", "sock_unix"}, Values: []uint64{18446744073709551615, 18446744073709551516}},
+ {Name: "tcp_seq_num", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"tcp_seq_num"}, Values: []uint64{1094861636}},
{Name: "uid", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"uid"}, Values: []uint64{0, 18446744073709551615}},
}
@@ -342,6 +343,10 @@ var structDescs_amd64 = []*KeyedStruct{
&IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", FldName: "pad1", TypeSize: 4, ArgDir: 1}}},
&IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", FldName: "pad2", TypeSize: 4, ArgDir: 1}}},
}}},
+ {Key: StructKey{Name: "tcp_resources", Dir: 1}, Desc: &StructDesc{TypeCommon: TypeCommon{TypeName: "tcp_resources", TypeSize: 8, ArgDir: 1}, Fields: []Type{
+ &ResourceType{TypeCommon: TypeCommon{TypeName: "tcp_seq_num", FldName: "seq", TypeSize: 4, ArgDir: 1}},
+ &ResourceType{TypeCommon: TypeCommon{TypeName: "tcp_seq_num", FldName: "ack", TypeSize: 4, ArgDir: 1}},
+ }}},
{Key: StructKey{Name: "termios"}, Desc: &StructDesc{TypeCommon: TypeCommon{TypeName: "termios", TypeSize: 44}, Fields: []Type{
&IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", FldName: "iflag", TypeSize: 4}}},
&IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", FldName: "oflag", TypeSize: 4}}},
@@ -1461,9 +1466,23 @@ var syscalls_amd64 = []*Syscall{
&PtrType{TypeCommon: TypeCommon{TypeName: "ptr", FldName: "new", TypeSize: 8}, Type: &BufferType{TypeCommon: TypeCommon{TypeName: "filename", IsVarlen: true}, Kind: 3}},
}},
{NR: 36, Name: "sync", CallName: "sync"},
+ {Name: "syz_emit_ethernet", CallName: "syz_emit_ethernet", Args: []Type{
+ &LenType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "len", FldName: "len", TypeSize: 8}}, Buf: "packet"},
+ &PtrType{TypeCommon: TypeCommon{TypeName: "ptr", FldName: "packet", TypeSize: 8}, Type: &BufferType{TypeCommon: TypeCommon{TypeName: "array", IsVarlen: true}}},
+ }},
{Name: "syz_execute_func", CallName: "syz_execute_func", Args: []Type{
&PtrType{TypeCommon: TypeCommon{TypeName: "ptr", FldName: "text", TypeSize: 8}, Type: &BufferType{TypeCommon: TypeCommon{TypeName: "text", IsVarlen: true}, Kind: 4}},
}},
+ {Name: "syz_extract_tcp_res", CallName: "syz_extract_tcp_res", Args: []Type{
+ &PtrType{TypeCommon: TypeCommon{TypeName: "ptr", FldName: "res", TypeSize: 8}, Type: &StructType{Key: StructKey{Name: "tcp_resources", Dir: 1}}},
+ &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", FldName: "seq_inc", TypeSize: 4}}},
+ &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", FldName: "ack_inc", TypeSize: 4}}},
+ }},
+ {Name: "syz_extract_tcp_res$synack", CallName: "syz_extract_tcp_res", Args: []Type{
+ &PtrType{TypeCommon: TypeCommon{TypeName: "ptr", FldName: "res", TypeSize: 8}, Type: &StructType{Key: StructKey{Name: "tcp_resources", Dir: 1}}},
+ &ConstType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "const", FldName: "seq_inc", TypeSize: 8}}, Val: 1},
+ &ConstType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "const", FldName: "ack_inc", TypeSize: 8}}},
+ }},
{Name: "syz_open_pts", CallName: "syz_open_pts", Ret: &ResourceType{TypeCommon: TypeCommon{TypeName: "fd_tty", FldName: "ret", TypeSize: 4, ArgDir: 1}}},
{NR: 200, Name: "truncate", CallName: "truncate", Args: []Type{
&PtrType{TypeCommon: TypeCommon{TypeName: "ptr", FldName: "file", TypeSize: 8}, Type: &BufferType{TypeCommon: TypeCommon{TypeName: "filename", IsVarlen: true}, Kind: 3}},
@@ -1893,4 +1912,4 @@ var consts_amd64 = []ConstValue{
{Name: "__MAP_NOREPLACE", Value: 2048},
}
-const revision_amd64 = "df30b58093a18d87ed6803bfe65ec9af86f721a3"
+const revision_amd64 = "05e6185f1ea57bbe311ffe3829b1cca890f472fc"
diff --git a/sys/openbsd/vnet.txt b/sys/openbsd/vnet.txt
new file mode 100644
index 000000000..1c9f99a04
--- /dev/null
+++ b/sys/openbsd/vnet.txt
@@ -0,0 +1,20 @@
+# Copyright 2018 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.
+
+# TODO(blackgnezdo): discover a cheap way to share protocol
+# descriptions between different OSs. They are platform agnostic
+# and should not need to be recreated on each platform.
+
+syz_emit_ethernet(len len[packet], packet ptr[in, array[int8]])
+
+resource tcp_seq_num[int32]: 0x41424344
+
+tcp_resources {
+ seq tcp_seq_num
+ ack tcp_seq_num
+}
+
+# These pseudo syscalls read a packet from tap device and extract tcp sequence and acknowledgement numbers from it.
+# They also adds the inc arguments to the returned values, this way sequence numbers get incremented.
+syz_extract_tcp_res(res ptr[out, tcp_resources], seq_inc int32, ack_inc int32)
+syz_extract_tcp_res$synack(res ptr[out, tcp_resources], seq_inc const[1], ack_inc const[0])