From 2bbe2f05585bb06f9c417ee8437a8077c97b0de2 Mon Sep 17 00:00:00 2001 From: Siddharth M Date: Sun, 14 Jul 2019 20:29:29 +0530 Subject: executor: add network packet injection for NetBSD * Initial Commit * working build of network packet fuzzing * Add missed csource file * pkg/csource: fix build * executor/common_bsd.h: Add comment stating reason for ifconfig create --- executor/common_bsd.h | 28 ++++++++++++++++++++++------ executor/defs.h | 2 +- executor/syscalls.h | 3 +++ pkg/csource/generated.go | 24 ++++++++++++++---------- pkg/host/host_netbsd.go | 1 + sys/netbsd/gen/amd64.go | 21 ++++++++++++++++++++- sys/netbsd/vnet.txt | 16 ++++++++++++++++ 7 files changed, 77 insertions(+), 18 deletions(-) create mode 100644 sys/netbsd/vnet.txt diff --git a/executor/common_bsd.h b/executor/common_bsd.h index d39d2aded..e483a41d1 100644 --- a/executor/common_bsd.h +++ b/executor/common_bsd.h @@ -37,7 +37,7 @@ static uintptr_t syz_open_pts(void) #endif // GOOS_openbsd -#if GOOS_freebsd || GOOS_openbsd +#if GOOS_freebsd || GOOS_openbsd || GOOS_netbsd #if SYZ_EXECUTOR || SYZ_TUN_ENABLE @@ -123,7 +123,18 @@ static void initialize_tun(int tun_id) char tun_device[sizeof(TUN_DEVICE)]; snprintf_check(tun_device, sizeof(tun_device), TUN_DEVICE, tun_id); + + char tun_iface[sizeof(TUN_IFACE)]; + snprintf_check(tun_iface, sizeof(tun_iface), TUN_IFACE, tun_id); + +#if GOOS_netbsd + // open(2) doesn't create an new tap/tun interface node + // so we use ifconfig to create the node. Might be casued due to regression + execute_command(0, "ifconfig %s destroy", tun_iface); + execute_command(0, "ifconfig %s create", tun_iface); +#else execute_command(0, "ifconfig %s destroy", tun_device); +#endif tunfd = open(tun_device, O_RDWR | O_NONBLOCK); #if GOOS_freebsd @@ -148,31 +159,36 @@ static void initialize_tun(int tun_id) close(tunfd); tunfd = kTunFd; - char tun_iface[sizeof(TUN_IFACE)]; - snprintf_check(tun_iface, sizeof(tun_iface), TUN_IFACE, tun_id); - char local_mac[sizeof(LOCAL_MAC)]; snprintf_check(local_mac, sizeof(local_mac), LOCAL_MAC); + + // Set the MAC address of the interface to LOCAL_MAC #if GOOS_openbsd execute_command(1, "ifconfig %s lladdr %s", tun_iface, local_mac); +#elif GOOS_netbsd + execute_command(1, "ifconfig %s link %s", tun_iface, local_mac); #else execute_command(1, "ifconfig %s ether %s", tun_iface, local_mac); #endif + // Setting up a static ip for the interface char local_ipv4[sizeof(LOCAL_IPV4)]; snprintf_check(local_ipv4, sizeof(local_ipv4), LOCAL_IPV4, tun_id); execute_command(1, "ifconfig %s inet %s netmask 255.255.255.0", tun_iface, local_ipv4); + // Creates an ARP table entry for the remote ip and MAC address char remote_mac[sizeof(REMOTE_MAC)]; char remote_ipv4[sizeof(REMOTE_IPV4)]; snprintf_check(remote_mac, sizeof(remote_mac), REMOTE_MAC); snprintf_check(remote_ipv4, sizeof(remote_ipv4), REMOTE_IPV4, tun_id); execute_command(0, "arp -s %s %s", remote_ipv4, remote_mac); + // Set up a static ipv6 address for the interface 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); + // Registers an NDP entry for the remote MAC with the remote ipv6 address char remote_ipv6[sizeof(REMOTE_IPV6)]; snprintf_check(remote_ipv6, sizeof(remote_ipv6), REMOTE_IPV6, tun_id); execute_command(0, "ndp -s %s%%%s %s", remote_ipv6, tun_iface, remote_mac); @@ -332,7 +348,7 @@ static void loop(); static int do_sandbox_none(void) { sandbox_common(); -#if (GOOS_freebsd || GOOS_openbsd) && (SYZ_EXECUTOR || SYZ_TUN_ENABLE) +#if (GOOS_freebsd || GOOS_openbsd || GOOS_netbsd) && (SYZ_EXECUTOR || SYZ_TUN_ENABLE) initialize_tun(procid); #endif loop(); @@ -367,7 +383,7 @@ static int do_sandbox_setuid(void) return wait_for_loop(pid); sandbox_common(); -#if (GOOS_freebsd || GOOS_openbsd) && (SYZ_EXECUTOR || SYZ_TUN_ENABLE) +#if (GOOS_freebsd || GOOS_openbsd || GOOS_netbsd) && (SYZ_EXECUTOR || SYZ_TUN_ENABLE) initialize_tun(procid); #endif diff --git a/executor/defs.h b/executor/defs.h index fe7d12e32..aa5a64c95 100644 --- a/executor/defs.h +++ b/executor/defs.h @@ -125,7 +125,7 @@ #if GOARCH_amd64 #define GOARCH "amd64" -#define SYZ_REVISION "71ea2d6047354a28057976d7ea40a5f24673a27c" +#define SYZ_REVISION "65d5b75dae9655ed21ef93383407c6108cf4de62" #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 3665c8897..fb6b5f64f 100644 --- a/executor/syscalls.h +++ b/executor/syscalls.h @@ -15804,7 +15804,10 @@ const call_t syscalls[] = { {"symlink", 57}, {"symlinkat", 470}, {"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}, {"truncate", 200}, {"unlink", 10}, {"unlinkat", 471}, diff --git a/pkg/csource/generated.go b/pkg/csource/generated.go index 766ab6e28..3db1ee059 100644 --- a/pkg/csource/generated.go +++ b/pkg/csource/generated.go @@ -430,7 +430,7 @@ static uintptr_t syz_open_pts(void) #endif -#if GOOS_freebsd || GOOS_openbsd +#if GOOS_freebsd || GOOS_openbsd || GOOS_netbsd #if SYZ_EXECUTOR || SYZ_TUN_ENABLE @@ -506,7 +506,16 @@ static void initialize_tun(int tun_id) char tun_device[sizeof(TUN_DEVICE)]; snprintf_check(tun_device, sizeof(tun_device), TUN_DEVICE, tun_id); + + char tun_iface[sizeof(TUN_IFACE)]; + snprintf_check(tun_iface, sizeof(tun_iface), TUN_IFACE, tun_id); + +#if GOOS_netbsd + execute_command(0, "ifconfig %s destroy", tun_iface); + execute_command(0, "ifconfig %s create", tun_iface); +#else execute_command(0, "ifconfig %s destroy", tun_device); +#endif tunfd = open(tun_device, O_RDWR | O_NONBLOCK); #if GOOS_freebsd @@ -529,31 +538,26 @@ static void initialize_tun(int tun_id) close(tunfd); tunfd = kTunFd; - char tun_iface[sizeof(TUN_IFACE)]; - snprintf_check(tun_iface, sizeof(tun_iface), TUN_IFACE, tun_id); - char local_mac[sizeof(LOCAL_MAC)]; snprintf_check(local_mac, sizeof(local_mac), LOCAL_MAC); #if GOOS_openbsd execute_command(1, "ifconfig %s lladdr %s", tun_iface, local_mac); +#elif GOOS_netbsd + execute_command(1, "ifconfig %s link %s", tun_iface, local_mac); #else execute_command(1, "ifconfig %s ether %s", tun_iface, local_mac); #endif - char local_ipv4[sizeof(LOCAL_IPV4)]; snprintf_check(local_ipv4, sizeof(local_ipv4), LOCAL_IPV4, tun_id); execute_command(1, "ifconfig %s inet %s netmask 255.255.255.0", tun_iface, local_ipv4); - char remote_mac[sizeof(REMOTE_MAC)]; char remote_ipv4[sizeof(REMOTE_IPV4)]; snprintf_check(remote_mac, sizeof(remote_mac), REMOTE_MAC); snprintf_check(remote_ipv4, sizeof(remote_ipv4), REMOTE_IPV4, tun_id); execute_command(0, "arp -s %s %s", remote_ipv4, remote_mac); - 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); - char remote_ipv6[sizeof(REMOTE_IPV6)]; snprintf_check(remote_ipv6, sizeof(remote_ipv6), REMOTE_IPV6, tun_id); execute_command(0, "ndp -s %s%%%s %s", remote_ipv6, tun_iface, remote_mac); @@ -701,7 +705,7 @@ static void loop(); static int do_sandbox_none(void) { sandbox_common(); -#if (GOOS_freebsd || GOOS_openbsd) && (SYZ_EXECUTOR || SYZ_TUN_ENABLE) +#if (GOOS_freebsd || GOOS_openbsd || GOOS_netbsd) && (SYZ_EXECUTOR || SYZ_TUN_ENABLE) initialize_tun(procid); #endif loop(); @@ -736,7 +740,7 @@ static int do_sandbox_setuid(void) return wait_for_loop(pid); sandbox_common(); -#if (GOOS_freebsd || GOOS_openbsd) && (SYZ_EXECUTOR || SYZ_TUN_ENABLE) +#if (GOOS_freebsd || GOOS_openbsd || GOOS_netbsd) && (SYZ_EXECUTOR || SYZ_TUN_ENABLE) initialize_tun(procid); #endif diff --git a/pkg/host/host_netbsd.go b/pkg/host/host_netbsd.go index 2ba822c36..609db091c 100644 --- a/pkg/host/host_netbsd.go +++ b/pkg/host/host_netbsd.go @@ -13,4 +13,5 @@ func isSupported(c *prog.Syscall, target *prog.Target, sandbox string) (bool, st func init() { checkFeature[FeatureCoverage] = unconditionallyEnabled + checkFeature[FeatureNetworkInjection] = unconditionallyEnabled } diff --git a/sys/netbsd/gen/amd64.go b/sys/netbsd/gen/amd64.go index a1d0e49cc..8697d5f7e 100644 --- a/sys/netbsd/gen/amd64.go +++ b/sys/netbsd/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}}, } @@ -344,6 +345,10 @@ var structDescs_amd64 = []*KeyedStruct{ &ConstType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "const", FldName: "pad1", TypeSize: 4, ArgDir: 1}}}, &ConstType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "const", 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: "timespec"}, Desc: &StructDesc{TypeCommon: TypeCommon{TypeName: "timespec", TypeSize: 16}, Fields: []Type{ &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "intptr", FldName: "sec", TypeSize: 8}}}, &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "intptr", FldName: "nsec", TypeSize: 8}}}, @@ -1347,9 +1352,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}}, Path: []string{"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}}}, + }}, {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}}, &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "intptr", FldName: "len", TypeSize: 8}}}, @@ -1791,4 +1810,4 @@ var consts_amd64 = []ConstValue{ {Name: "_UC_STACK", Value: 2}, } -const revision_amd64 = "71ea2d6047354a28057976d7ea40a5f24673a27c" +const revision_amd64 = "65d5b75dae9655ed21ef93383407c6108cf4de62" diff --git a/sys/netbsd/vnet.txt b/sys/netbsd/vnet.txt new file mode 100644 index 000000000..0e9dbc53f --- /dev/null +++ b/sys/netbsd/vnet.txt @@ -0,0 +1,16 @@ +# 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. + +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]) -- cgit mrf-deployment