mirror of
https://github.com/reactos/syzkaller.git
synced 2025-02-06 03:38:52 +00:00
Merge pull request #175 from xairy/up-tcp-sequence
sys, executor: extract tcp sequence numbers from /dev/net/tun
This commit is contained in:
commit
8320ea0056
@ -21,10 +21,15 @@ var commonHeader = `
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <linux/capability.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/if_tun.h>
|
||||
#include <linux/kvm.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/if_tun.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <net/if_arp.h>
|
||||
|
||||
#include <assert.h>
|
||||
@ -162,7 +167,11 @@ static void install_segv_handler()
|
||||
*(type*)(addr) = new_val; \
|
||||
}
|
||||
|
||||
#ifdef __NR_syz_emit_ethernet
|
||||
#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)
|
||||
{
|
||||
int rv;
|
||||
@ -203,6 +212,8 @@ static void execute_command(const char* format, ...)
|
||||
|
||||
int tunfd = -1;
|
||||
|
||||
#define SYZ_TUN_MAX_PACKET_SIZE (64 << 10)
|
||||
|
||||
#define MAX_PIDS 32
|
||||
#define ADDR_MAX_LEN 32
|
||||
|
||||
@ -212,8 +223,8 @@ int tunfd = -1;
|
||||
#define LOCAL_IPV4 "172.20.%d.170"
|
||||
#define REMOTE_IPV4 "172.20.%d.187"
|
||||
|
||||
#define LOCAL_IPV6 "fd00::%02hxaa"
|
||||
#define REMOTE_IPV6 "fd00::%02hxbb"
|
||||
#define LOCAL_IPV6 "fe80::%02hxaa"
|
||||
#define REMOTE_IPV6 "fe80::%02hxbb"
|
||||
|
||||
static void initialize_tun(uint64_t pid)
|
||||
{
|
||||
@ -221,7 +232,7 @@ static void initialize_tun(uint64_t pid)
|
||||
fail("tun: no more than %d executors", MAX_PIDS);
|
||||
int id = pid;
|
||||
|
||||
tunfd = open("/dev/net/tun", O_RDWR);
|
||||
tunfd = open("/dev/net/tun", O_RDWR | O_NONBLOCK);
|
||||
if (tunfd == -1)
|
||||
fail("tun: can't open /dev/net/tun");
|
||||
|
||||
@ -250,12 +261,16 @@ static void initialize_tun(uint64_t pid)
|
||||
char remote_ipv6[ADDR_MAX_LEN];
|
||||
snprintf_check(remote_ipv6, sizeof(remote_ipv6), REMOTE_IPV6, id);
|
||||
|
||||
execute_command("sysctl -w net.ipv6.conf.%s.accept_dad=0", iface);
|
||||
|
||||
execute_command("sysctl -w net.ipv6.conf.%s.router_solicitations=0", iface);
|
||||
|
||||
execute_command("ip link set dev %s address %s", iface, local_mac);
|
||||
execute_command("ip addr add %s/24 dev %s", local_ipv4, iface);
|
||||
execute_command("ip -6 addr add %s/120 dev %s", local_ipv6, iface);
|
||||
execute_command("ip neigh add %s lladdr %s dev %s nud permanent", remote_ipv4, remote_mac, iface);
|
||||
execute_command("ip -6 neigh add %s lladdr %s dev %s nud permanent", remote_ipv6, remote_mac, iface);
|
||||
execute_command("ip link set %s up", iface);
|
||||
execute_command("ip link set dev %s up", iface);
|
||||
}
|
||||
|
||||
static void setup_tun(uint64_t pid, bool enable_tun)
|
||||
@ -264,17 +279,120 @@ static void setup_tun(uint64_t pid, bool enable_tun)
|
||||
initialize_tun(pid);
|
||||
}
|
||||
|
||||
void debug_dump_data(const char* data, int length)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < length; i++) {
|
||||
debug("%02hx ", (uint8_t)data[i] & (uint8_t)0xff);
|
||||
if (i % 16 == 15)
|
||||
debug("\n");
|
||||
}
|
||||
if (i % 16 != 0)
|
||||
debug("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __NR_syz_emit_ethernet
|
||||
static uintptr_t syz_emit_ethernet(uintptr_t a0, uintptr_t a1)
|
||||
{
|
||||
|
||||
if (tunfd < 0)
|
||||
return (uintptr_t)-1;
|
||||
|
||||
int64_t length = a0;
|
||||
char* data = (char*)a1;
|
||||
debug_dump_data(data, length);
|
||||
return write(tunfd, data, length);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __NR_syz_extract_tcp_res
|
||||
struct ipv6hdr {
|
||||
__u8 priority : 4,
|
||||
version : 4;
|
||||
__u8 flow_lbl[3];
|
||||
|
||||
__be16 payload_len;
|
||||
__u8 nexthdr;
|
||||
__u8 hop_limit;
|
||||
|
||||
struct in6_addr saddr;
|
||||
struct in6_addr daddr;
|
||||
};
|
||||
|
||||
struct tcp_resources {
|
||||
int32_t seq;
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
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 ethhdr))
|
||||
return (uintptr_t)-1;
|
||||
struct ethhdr* ethhdr = (struct ethhdr*)&data[0];
|
||||
|
||||
if (ethhdr->h_proto == htons(ETH_P_IP)) {
|
||||
if (length < sizeof(struct ethhdr) + sizeof(struct iphdr))
|
||||
return (uintptr_t)-1;
|
||||
struct iphdr* iphdr = (struct iphdr*)&data[sizeof(struct ethhdr)];
|
||||
if (iphdr->protocol != IPPROTO_TCP)
|
||||
return (uintptr_t)-1;
|
||||
if (length < sizeof(struct ethhdr) + iphdr->ihl * 4 + sizeof(struct tcphdr))
|
||||
return (uintptr_t)-1;
|
||||
tcphdr = (struct tcphdr*)&data[sizeof(struct ethhdr) + iphdr->ihl * 4];
|
||||
} else {
|
||||
if (length < sizeof(struct ethhdr) + sizeof(struct ipv6hdr))
|
||||
return (uintptr_t)-1;
|
||||
struct ipv6hdr* ipv6hdr = (struct ipv6hdr*)&data[sizeof(struct ethhdr)];
|
||||
if (ipv6hdr->nexthdr != IPPROTO_TCP)
|
||||
return (uintptr_t)-1;
|
||||
if (length < sizeof(struct ethhdr) + sizeof(struct ipv6hdr) + sizeof(struct tcphdr))
|
||||
return (uintptr_t)-1;
|
||||
tcphdr = (struct tcphdr*)&data[sizeof(struct ethhdr) + sizeof(struct ipv6hdr)];
|
||||
}
|
||||
|
||||
struct tcp_resources* res = (struct tcp_resources*)a0;
|
||||
NONFAILING(res->seq = htonl((ntohl(tcphdr->seq) + (uint32_t)a1)));
|
||||
NONFAILING(res->ack = htonl((ntohl(tcphdr->ack_seq) + (uint32_t)a2)));
|
||||
|
||||
debug("extracted seq: %08x\n", res->seq);
|
||||
debug("extracted ack: %08x\n", res->ack);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct csum_inet {
|
||||
uint32_t acc;
|
||||
};
|
||||
@ -1387,6 +1505,10 @@ static uintptr_t execute_syscall(int nr, uintptr_t a0, uintptr_t a1, uintptr_t a
|
||||
case __NR_syz_emit_ethernet:
|
||||
return syz_emit_ethernet(a0, a1);
|
||||
#endif
|
||||
#ifdef __NR_syz_extract_tcp_res
|
||||
case __NR_syz_extract_tcp_res:
|
||||
return syz_extract_tcp_res(a0, a1, a2);
|
||||
#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);
|
||||
@ -1444,7 +1566,7 @@ static int do_sandbox_none(int executor_pid, bool enable_tun)
|
||||
return pid;
|
||||
|
||||
sandbox_common();
|
||||
#ifdef __NR_syz_emit_ethernet
|
||||
#ifdef SYZ_TUN_ENABLE
|
||||
setup_tun(executor_pid, enable_tun);
|
||||
#endif
|
||||
|
||||
@ -1461,7 +1583,7 @@ static int do_sandbox_setuid(int executor_pid, bool enable_tun)
|
||||
return pid;
|
||||
|
||||
sandbox_common();
|
||||
#ifdef __NR_syz_emit_ethernet
|
||||
#ifdef SYZ_TUN_ENABLE
|
||||
setup_tun(executor_pid, enable_tun);
|
||||
#endif
|
||||
|
||||
@ -1518,7 +1640,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 __NR_syz_emit_ethernet
|
||||
#ifdef SYZ_TUN_ENABLE
|
||||
setup_tun(epid, etun);
|
||||
#endif
|
||||
|
||||
|
@ -54,6 +54,9 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) {
|
||||
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 {
|
||||
@ -278,7 +281,7 @@ loop:
|
||||
case prog.ExecArgResult:
|
||||
fmt.Fprintf(w, ", %v", resultRef())
|
||||
default:
|
||||
panic("unknown arg type")
|
||||
panic(fmt.Sprintf("unknown arg type %v", typ))
|
||||
}
|
||||
}
|
||||
for i := nargs; i < 9; i++ {
|
||||
|
@ -20,10 +20,15 @@
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <linux/capability.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/if_tun.h>
|
||||
#include <linux/kvm.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/if_tun.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <net/if_arp.h>
|
||||
|
||||
#include <assert.h>
|
||||
@ -184,7 +189,11 @@ static void install_segv_handler()
|
||||
*(type*)(addr) = new_val; \
|
||||
}
|
||||
|
||||
#ifdef __NR_syz_emit_ethernet
|
||||
#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)
|
||||
{
|
||||
int rv;
|
||||
@ -225,6 +234,8 @@ static void execute_command(const char* format, ...)
|
||||
|
||||
int tunfd = -1;
|
||||
|
||||
#define SYZ_TUN_MAX_PACKET_SIZE (64 << 10)
|
||||
|
||||
// sysgen knowns about this constant (maxPids)
|
||||
#define MAX_PIDS 32
|
||||
#define ADDR_MAX_LEN 32
|
||||
@ -235,8 +246,8 @@ int tunfd = -1;
|
||||
#define LOCAL_IPV4 "172.20.%d.170"
|
||||
#define REMOTE_IPV4 "172.20.%d.187"
|
||||
|
||||
#define LOCAL_IPV6 "fd00::%02hxaa"
|
||||
#define REMOTE_IPV6 "fd00::%02hxbb"
|
||||
#define LOCAL_IPV6 "fe80::%02hxaa"
|
||||
#define REMOTE_IPV6 "fe80::%02hxbb"
|
||||
|
||||
static void initialize_tun(uint64_t pid)
|
||||
{
|
||||
@ -244,7 +255,7 @@ static void initialize_tun(uint64_t pid)
|
||||
fail("tun: no more than %d executors", MAX_PIDS);
|
||||
int id = pid;
|
||||
|
||||
tunfd = open("/dev/net/tun", O_RDWR);
|
||||
tunfd = open("/dev/net/tun", O_RDWR | O_NONBLOCK);
|
||||
if (tunfd == -1)
|
||||
fail("tun: can't open /dev/net/tun");
|
||||
|
||||
@ -273,12 +284,19 @@ static void initialize_tun(uint64_t pid)
|
||||
char remote_ipv6[ADDR_MAX_LEN];
|
||||
snprintf_check(remote_ipv6, sizeof(remote_ipv6), REMOTE_IPV6, id);
|
||||
|
||||
// Disable IPv6 DAD, otherwise the address remains unusable until DAD completes.
|
||||
execute_command("sysctl -w net.ipv6.conf.%s.accept_dad=0", iface);
|
||||
|
||||
// Disable IPv6 router solicitation to prevent IPv6 spam.
|
||||
execute_command("sysctl -w net.ipv6.conf.%s.router_solicitations=0", iface);
|
||||
// There seems to be no way to disable IPv6 MTD to prevent more IPv6 spam.
|
||||
|
||||
execute_command("ip link set dev %s address %s", iface, local_mac);
|
||||
execute_command("ip addr add %s/24 dev %s", local_ipv4, iface);
|
||||
execute_command("ip -6 addr add %s/120 dev %s", local_ipv6, iface);
|
||||
execute_command("ip neigh add %s lladdr %s dev %s nud permanent", remote_ipv4, remote_mac, iface);
|
||||
execute_command("ip -6 neigh add %s lladdr %s dev %s nud permanent", remote_ipv6, remote_mac, iface);
|
||||
execute_command("ip link set %s up", iface);
|
||||
execute_command("ip link set dev %s up", iface);
|
||||
}
|
||||
|
||||
static void setup_tun(uint64_t pid, bool enable_tun)
|
||||
@ -287,16 +305,124 @@ static void setup_tun(uint64_t pid, bool enable_tun)
|
||||
initialize_tun(pid);
|
||||
}
|
||||
|
||||
void debug_dump_data(const char* data, int length)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < length; i++) {
|
||||
debug("%02hx ", (uint8_t)data[i] & (uint8_t)0xff);
|
||||
if (i % 16 == 15)
|
||||
debug("\n");
|
||||
}
|
||||
if (i % 16 != 0)
|
||||
debug("\n");
|
||||
}
|
||||
#endif // SYZ_TUN_ENABLE
|
||||
|
||||
#ifdef __NR_syz_emit_ethernet
|
||||
static uintptr_t syz_emit_ethernet(uintptr_t a0, uintptr_t a1)
|
||||
{
|
||||
// syz_emit_ethernet(len len[packet], packet ptr[in, eth_packet])
|
||||
|
||||
if (tunfd < 0)
|
||||
return (uintptr_t)-1;
|
||||
|
||||
int64_t length = a0;
|
||||
char* data = (char*)a1;
|
||||
debug_dump_data(data, length);
|
||||
return write(tunfd, data, length);
|
||||
}
|
||||
#endif // __NR_syz_emit_ethernet
|
||||
#endif
|
||||
|
||||
#ifdef __NR_syz_extract_tcp_res
|
||||
// Can't include <linux/ipv6.h>, since it causes
|
||||
// conflicts due to some structs redefinition.
|
||||
struct ipv6hdr {
|
||||
__u8 priority : 4,
|
||||
version : 4;
|
||||
__u8 flow_lbl[3];
|
||||
|
||||
__be16 payload_len;
|
||||
__u8 nexthdr;
|
||||
__u8 hop_limit;
|
||||
|
||||
struct in6_addr saddr;
|
||||
struct in6_addr daddr;
|
||||
};
|
||||
|
||||
struct tcp_resources {
|
||||
int32_t seq;
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
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 ethhdr))
|
||||
return (uintptr_t)-1;
|
||||
struct ethhdr* ethhdr = (struct ethhdr*)&data[0];
|
||||
|
||||
if (ethhdr->h_proto == htons(ETH_P_IP)) {
|
||||
if (length < sizeof(struct ethhdr) + sizeof(struct iphdr))
|
||||
return (uintptr_t)-1;
|
||||
struct iphdr* iphdr = (struct iphdr*)&data[sizeof(struct ethhdr)];
|
||||
if (iphdr->protocol != IPPROTO_TCP)
|
||||
return (uintptr_t)-1;
|
||||
if (length < sizeof(struct ethhdr) + iphdr->ihl * 4 + sizeof(struct tcphdr))
|
||||
return (uintptr_t)-1;
|
||||
tcphdr = (struct tcphdr*)&data[sizeof(struct ethhdr) + iphdr->ihl * 4];
|
||||
} else {
|
||||
if (length < sizeof(struct ethhdr) + sizeof(struct ipv6hdr))
|
||||
return (uintptr_t)-1;
|
||||
struct ipv6hdr* ipv6hdr = (struct ipv6hdr*)&data[sizeof(struct ethhdr)];
|
||||
// TODO: parse and skip extension headers.
|
||||
if (ipv6hdr->nexthdr != IPPROTO_TCP)
|
||||
return (uintptr_t)-1;
|
||||
if (length < sizeof(struct ethhdr) + sizeof(struct ipv6hdr) + sizeof(struct tcphdr))
|
||||
return (uintptr_t)-1;
|
||||
tcphdr = (struct tcphdr*)&data[sizeof(struct ethhdr) + sizeof(struct ipv6hdr)];
|
||||
}
|
||||
|
||||
struct tcp_resources* res = (struct tcp_resources*)a0;
|
||||
NONFAILING(res->seq = htonl((ntohl(tcphdr->seq) + (uint32_t)a1)));
|
||||
NONFAILING(res->ack = htonl((ntohl(tcphdr->ack_seq) + (uint32_t)a2)));
|
||||
|
||||
debug("extracted seq: %08x\n", res->seq);
|
||||
debug("extracted ack: %08x\n", res->ack);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct csum_inet {
|
||||
uint32_t acc;
|
||||
@ -469,6 +595,10 @@ static uintptr_t execute_syscall(int nr, uintptr_t a0, uintptr_t a1, uintptr_t a
|
||||
case __NR_syz_emit_ethernet:
|
||||
return syz_emit_ethernet(a0, a1);
|
||||
#endif
|
||||
#ifdef __NR_syz_extract_tcp_res
|
||||
case __NR_syz_extract_tcp_res:
|
||||
return syz_extract_tcp_res(a0, a1, a2);
|
||||
#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);
|
||||
@ -530,7 +660,7 @@ static int do_sandbox_none(int executor_pid, bool enable_tun)
|
||||
return pid;
|
||||
|
||||
sandbox_common();
|
||||
#ifdef __NR_syz_emit_ethernet
|
||||
#ifdef SYZ_TUN_ENABLE
|
||||
setup_tun(executor_pid, enable_tun);
|
||||
#endif
|
||||
|
||||
@ -547,7 +677,7 @@ static int do_sandbox_setuid(int executor_pid, bool enable_tun)
|
||||
return pid;
|
||||
|
||||
sandbox_common();
|
||||
#ifdef __NR_syz_emit_ethernet
|
||||
#ifdef SYZ_TUN_ENABLE
|
||||
setup_tun(executor_pid, enable_tun);
|
||||
#endif
|
||||
|
||||
@ -608,7 +738,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 __NR_syz_emit_ethernet
|
||||
#ifdef SYZ_TUN_ENABLE
|
||||
// For sandbox namespace we setup tun after initializing uid mapping,
|
||||
// otherwise ip commands fail.
|
||||
setup_tun(epid, etun);
|
||||
|
@ -256,6 +256,11 @@ void loop()
|
||||
fail("failed to chdir");
|
||||
close(kInPipeFd);
|
||||
close(kOutPipeFd);
|
||||
if (flag_enable_tun) {
|
||||
// Read all remaining packets from tun to better
|
||||
// isolate consequently executing programs.
|
||||
flush_tun();
|
||||
}
|
||||
execute_one();
|
||||
debug("worker exiting\n");
|
||||
doexit(0);
|
||||
|
@ -98,7 +98,7 @@ func isSupportedSyzkall(c *sys.Call) bool {
|
||||
case "syz_fuseblk_mount":
|
||||
_, err := os.Stat("/dev/fuse")
|
||||
return err == nil && syscall.Getuid() == 0
|
||||
case "syz_emit_ethernet":
|
||||
case "syz_emit_ethernet", "syz_extract_tcp_res":
|
||||
fd, err := syscall.Open("/dev/net/tun", syscall.O_RDWR, 0)
|
||||
if err == nil {
|
||||
syscall.Close(fd)
|
||||
|
@ -98,6 +98,12 @@ func (a *Arg) Value(pid int) uintptr {
|
||||
case *sys.CsumType:
|
||||
// Checksums are computed dynamically in executor.
|
||||
return 0
|
||||
case *sys.ResourceType:
|
||||
if t, ok := typ.Desc.Type.(*sys.IntType); ok {
|
||||
return encodeValue(a.Val, t.Size(), t.BigEndian)
|
||||
} else {
|
||||
panic(fmt.Sprintf("bad base type for a resource: %v", t))
|
||||
}
|
||||
case *sys.ProcType:
|
||||
val := uintptr(typ.ValuesStart) + uintptr(typ.ValuesPerProc)*uintptr(pid) + a.Val
|
||||
return encodeValue(val, typ.Size(), typ.BigEndian)
|
||||
|
42
sys/vnet.txt
42
sys/vnet.txt
@ -6,6 +6,18 @@ include <linux/byteorder/generic.h>
|
||||
|
||||
syz_emit_ethernet(len len[packet], packet ptr[in, eth_packet])
|
||||
|
||||
resource tcp_seq_num[int32]: 0x42424242
|
||||
|
||||
tcp_resources {
|
||||
seq tcp_seq_num
|
||||
ack tcp_seq_num
|
||||
}
|
||||
|
||||
# These pseudo syscalls read a packet from /dev/net/tun 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])
|
||||
|
||||
################################################################################
|
||||
################################### Ethernet ###################################
|
||||
################################################################################
|
||||
@ -440,20 +452,22 @@ ipv6_addr_empty {
|
||||
a0 array[const[0x00, int8], 16]
|
||||
}
|
||||
|
||||
# This corresponds to LOCAL_IPV6 ("fd00::%02hxaa" % pid) in executor/common.h
|
||||
# This corresponds to LOCAL_IPV6 ("fe80::%02hxaa" % pid) in executor/common.h
|
||||
ipv6_addr_local {
|
||||
a0 const[0xfd, int8]
|
||||
a1 array[const[0x00, int8], 13]
|
||||
a2 proc[int8, 0, 1]
|
||||
a3 const[0xaa, int8]
|
||||
a0 const[0xfe, int8]
|
||||
a1 const[0x80, int8]
|
||||
a2 array[const[0x00, int8], 12]
|
||||
a3 proc[int8, 0, 1]
|
||||
a4 const[0xaa, int8]
|
||||
} [packed]
|
||||
|
||||
# This corresponds to REMOTE_IPV6 ("fd00::%02hxbb" % pid) in executor/common.h
|
||||
# This corresponds to REMOTE_IPV6 ("fe80::%02hxbb" % pid) in executor/common.h
|
||||
ipv6_addr_remote {
|
||||
a0 const[0xfd, int8]
|
||||
a1 array[const[0x00, int8], 13]
|
||||
a2 proc[int8, 0, 1]
|
||||
a3 const[0xbb, int8]
|
||||
a0 const[0xfe, int8]
|
||||
a1 const[0x80, int8]
|
||||
a2 array[const[0x00, int8], 12]
|
||||
a3 proc[int8, 0, 1]
|
||||
a4 const[0xbb, int8]
|
||||
} [packed]
|
||||
|
||||
ipv6_addr_loopback {
|
||||
@ -660,14 +674,6 @@ tcp_options {
|
||||
options array[tcp_option]
|
||||
} [packed, align_4]
|
||||
|
||||
# TODO: extract sequence numbers from packets
|
||||
tcp_seq_num [
|
||||
init const[0x56565656, int32be]
|
||||
next const[0x56565657, int32be]
|
||||
nextn int32be[0x56565656:0x56566000]
|
||||
random int32be
|
||||
]
|
||||
|
||||
tcp_flags = 0, TCPHDR_FIN, TCPHDR_SYN, TCPHDR_RST, TCPHDR_PSH, TCPHDR_ACK, TCPHDR_URG, TCPHDR_ECE, TCPHDR_CWR, TCPHDR_SYN_ECN
|
||||
|
||||
tcp_header {
|
||||
|
@ -23,13 +23,14 @@ var archs = []*Arch{
|
||||
}
|
||||
|
||||
var syzkalls = map[string]uint64{
|
||||
"syz_test": 1000001,
|
||||
"syz_open_dev": 1000002,
|
||||
"syz_open_pts": 1000003,
|
||||
"syz_fuse_mount": 1000004,
|
||||
"syz_fuseblk_mount": 1000005,
|
||||
"syz_emit_ethernet": 1000006,
|
||||
"syz_kvm_setup_cpu": 1000007,
|
||||
"syz_test": 1000001,
|
||||
"syz_open_dev": 1000002,
|
||||
"syz_open_pts": 1000003,
|
||||
"syz_fuse_mount": 1000004,
|
||||
"syz_fuseblk_mount": 1000005,
|
||||
"syz_emit_ethernet": 1000006,
|
||||
"syz_kvm_setup_cpu": 1000007,
|
||||
"syz_extract_tcp_res": 1000008,
|
||||
}
|
||||
|
||||
func generateExecutorSyscalls(syscalls []Syscall, consts map[string]map[string]uint64) {
|
||||
|
@ -186,6 +186,9 @@ func main() {
|
||||
if _, ok := calls[sys.CallMap["syz_emit_ethernet"]]; ok {
|
||||
config.Flags |= ipc.FlagEnableTun
|
||||
}
|
||||
if _, ok := calls[sys.CallMap["syz_extract_tcp_res"]]; ok {
|
||||
config.Flags |= ipc.FlagEnableTun
|
||||
}
|
||||
noCover = config.Flags&ipc.FlagSignal == 0
|
||||
leakCallback := func() {
|
||||
if atomic.LoadUint32(&allTriaged) != 0 {
|
||||
|
@ -74,7 +74,7 @@ func main() {
|
||||
handled[call.Meta.CallName] = true
|
||||
}
|
||||
}
|
||||
if handled["syz_emit_ethernet"] {
|
||||
if handled["syz_emit_ethernet"] || handled["syz_extract_tcp_res"] {
|
||||
config.Flags |= ipc.FlagEnableTun
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user