// https://syzkaller.appspot.com/bug?id=4d7de0e6a195b6a5ffef01d2776e737a52c7de60 // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static unsigned long long procid; static void sleep_ms(uint64_t ms) { usleep(ms * 1000); } static uint64_t current_time_ms(void) { struct timespec ts; if (clock_gettime(CLOCK_MONOTONIC, &ts)) exit(1); return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; } static void use_temporary_dir(void) { char tmpdir_template[] = "./syzkaller.XXXXXX"; char* tmpdir = mkdtemp(tmpdir_template); if (!tmpdir) exit(1); if (chmod(tmpdir, 0777)) exit(1); if (chdir(tmpdir)) exit(1); } static void thread_start(void* (*fn)(void*), void* arg) { pthread_t th; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setstacksize(&attr, 128 << 10); int i = 0; for (; i < 100; i++) { if (pthread_create(&th, &attr, fn, arg) == 0) { pthread_attr_destroy(&attr); return; } if (errno == EAGAIN) { usleep(50); continue; } break; } exit(1); } typedef struct { int state; } event_t; static void event_init(event_t* ev) { ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { if (ev->state) exit(1); __atomic_store_n(&ev->state, 1, __ATOMIC_RELEASE); syscall(SYS_futex, &ev->state, FUTEX_WAKE | FUTEX_PRIVATE_FLAG, 1000000); } static void event_wait(event_t* ev) { while (!__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE)) syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, 0); } static int event_isset(event_t* ev) { return __atomic_load_n(&ev->state, __ATOMIC_ACQUIRE); } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; for (;;) { uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, &ts); if (__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE)) return 1; now = current_time_ms(); if (now - start > timeout) return 0; } } static bool write_file(const char* file, const char* what, ...) { char buf[1024]; va_list args; va_start(args, what); vsnprintf(buf, sizeof(buf), what, args); va_end(args); buf[sizeof(buf) - 1] = 0; int len = strlen(buf); int fd = open(file, O_WRONLY | O_CLOEXEC); if (fd == -1) return false; if (write(fd, buf, len) != len) { int err = errno; close(fd); errno = err; return false; } close(fd); return true; } struct nlmsg { char* pos; int nesting; struct nlattr* nested[8]; char buf[4096]; }; static void netlink_init(struct nlmsg* nlmsg, int typ, int flags, const void* data, int size) { memset(nlmsg, 0, sizeof(*nlmsg)); struct nlmsghdr* hdr = (struct nlmsghdr*)nlmsg->buf; hdr->nlmsg_type = typ; hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | flags; memcpy(hdr + 1, data, size); nlmsg->pos = (char*)(hdr + 1) + NLMSG_ALIGN(size); } static void netlink_attr(struct nlmsg* nlmsg, int typ, const void* data, int size) { struct nlattr* attr = (struct nlattr*)nlmsg->pos; attr->nla_len = sizeof(*attr) + size; attr->nla_type = typ; if (size > 0) memcpy(attr + 1, data, size); nlmsg->pos += NLMSG_ALIGN(attr->nla_len); } static void netlink_nest(struct nlmsg* nlmsg, int typ) { struct nlattr* attr = (struct nlattr*)nlmsg->pos; attr->nla_type = typ; nlmsg->pos += sizeof(*attr); nlmsg->nested[nlmsg->nesting++] = attr; } static void netlink_done(struct nlmsg* nlmsg) { struct nlattr* attr = nlmsg->nested[--nlmsg->nesting]; attr->nla_len = nlmsg->pos - (char*)attr; } static int netlink_send_ext(struct nlmsg* nlmsg, int sock, uint16_t reply_type, int* reply_len, bool dofail) { if (nlmsg->pos > nlmsg->buf + sizeof(nlmsg->buf) || nlmsg->nesting) exit(1); struct nlmsghdr* hdr = (struct nlmsghdr*)nlmsg->buf; hdr->nlmsg_len = nlmsg->pos - nlmsg->buf; struct sockaddr_nl addr; memset(&addr, 0, sizeof(addr)); addr.nl_family = AF_NETLINK; ssize_t n = sendto(sock, nlmsg->buf, hdr->nlmsg_len, 0, (struct sockaddr*)&addr, sizeof(addr)); if (n != (ssize_t)hdr->nlmsg_len) { if (dofail) exit(1); return -1; } n = recv(sock, nlmsg->buf, sizeof(nlmsg->buf), 0); if (reply_len) *reply_len = 0; if (n < 0) { if (dofail) exit(1); return -1; } if (n < (ssize_t)sizeof(struct nlmsghdr)) { errno = EINVAL; if (dofail) exit(1); return -1; } if (hdr->nlmsg_type == NLMSG_DONE) return 0; if (reply_len && hdr->nlmsg_type == reply_type) { *reply_len = n; return 0; } if (n < (ssize_t)(sizeof(struct nlmsghdr) + sizeof(struct nlmsgerr))) { errno = EINVAL; if (dofail) exit(1); return -1; } if (hdr->nlmsg_type != NLMSG_ERROR) { errno = EINVAL; if (dofail) exit(1); return -1; } errno = -((struct nlmsgerr*)(hdr + 1))->error; return -errno; } static int netlink_send(struct nlmsg* nlmsg, int sock) { return netlink_send_ext(nlmsg, sock, 0, NULL, true); } static int netlink_query_family_id(struct nlmsg* nlmsg, int sock, const char* family_name, bool dofail) { struct genlmsghdr genlhdr; memset(&genlhdr, 0, sizeof(genlhdr)); genlhdr.cmd = CTRL_CMD_GETFAMILY; netlink_init(nlmsg, GENL_ID_CTRL, 0, &genlhdr, sizeof(genlhdr)); netlink_attr(nlmsg, CTRL_ATTR_FAMILY_NAME, family_name, strnlen(family_name, GENL_NAMSIZ - 1) + 1); int n = 0; int err = netlink_send_ext(nlmsg, sock, GENL_ID_CTRL, &n, dofail); if (err < 0) { return -1; } uint16_t id = 0; struct nlattr* attr = (struct nlattr*)(nlmsg->buf + NLMSG_HDRLEN + NLMSG_ALIGN(sizeof(genlhdr))); for (; (char*)attr < nlmsg->buf + n; attr = (struct nlattr*)((char*)attr + NLMSG_ALIGN(attr->nla_len))) { if (attr->nla_type == CTRL_ATTR_FAMILY_ID) { id = *(uint16_t*)(attr + 1); break; } } if (!id) { errno = EINVAL; return -1; } recv(sock, nlmsg->buf, sizeof(nlmsg->buf), 0); return id; } static int netlink_next_msg(struct nlmsg* nlmsg, unsigned int offset, unsigned int total_len) { struct nlmsghdr* hdr = (struct nlmsghdr*)(nlmsg->buf + offset); if (offset == total_len || offset + hdr->nlmsg_len > total_len) return -1; return hdr->nlmsg_len; } static void netlink_add_device_impl(struct nlmsg* nlmsg, const char* type, const char* name) { struct ifinfomsg hdr; memset(&hdr, 0, sizeof(hdr)); netlink_init(nlmsg, RTM_NEWLINK, NLM_F_EXCL | NLM_F_CREATE, &hdr, sizeof(hdr)); if (name) netlink_attr(nlmsg, IFLA_IFNAME, name, strlen(name)); netlink_nest(nlmsg, IFLA_LINKINFO); netlink_attr(nlmsg, IFLA_INFO_KIND, type, strlen(type)); } static void netlink_add_device(struct nlmsg* nlmsg, int sock, const char* type, const char* name) { netlink_add_device_impl(nlmsg, type, name); netlink_done(nlmsg); int err = netlink_send(nlmsg, sock); if (err < 0) { } } static void netlink_add_veth(struct nlmsg* nlmsg, int sock, const char* name, const char* peer) { netlink_add_device_impl(nlmsg, "veth", name); netlink_nest(nlmsg, IFLA_INFO_DATA); netlink_nest(nlmsg, VETH_INFO_PEER); nlmsg->pos += sizeof(struct ifinfomsg); netlink_attr(nlmsg, IFLA_IFNAME, peer, strlen(peer)); netlink_done(nlmsg); netlink_done(nlmsg); netlink_done(nlmsg); int err = netlink_send(nlmsg, sock); if (err < 0) { } } static void netlink_add_hsr(struct nlmsg* nlmsg, int sock, const char* name, const char* slave1, const char* slave2) { netlink_add_device_impl(nlmsg, "hsr", name); netlink_nest(nlmsg, IFLA_INFO_DATA); int ifindex1 = if_nametoindex(slave1); netlink_attr(nlmsg, IFLA_HSR_SLAVE1, &ifindex1, sizeof(ifindex1)); int ifindex2 = if_nametoindex(slave2); netlink_attr(nlmsg, IFLA_HSR_SLAVE2, &ifindex2, sizeof(ifindex2)); netlink_done(nlmsg); netlink_done(nlmsg); int err = netlink_send(nlmsg, sock); if (err < 0) { } } static void netlink_add_linked(struct nlmsg* nlmsg, int sock, const char* type, const char* name, const char* link) { netlink_add_device_impl(nlmsg, type, name); netlink_done(nlmsg); int ifindex = if_nametoindex(link); netlink_attr(nlmsg, IFLA_LINK, &ifindex, sizeof(ifindex)); int err = netlink_send(nlmsg, sock); if (err < 0) { } } static void netlink_add_vlan(struct nlmsg* nlmsg, int sock, const char* name, const char* link, uint16_t id, uint16_t proto) { netlink_add_device_impl(nlmsg, "vlan", name); netlink_nest(nlmsg, IFLA_INFO_DATA); netlink_attr(nlmsg, IFLA_VLAN_ID, &id, sizeof(id)); netlink_attr(nlmsg, IFLA_VLAN_PROTOCOL, &proto, sizeof(proto)); netlink_done(nlmsg); netlink_done(nlmsg); int ifindex = if_nametoindex(link); netlink_attr(nlmsg, IFLA_LINK, &ifindex, sizeof(ifindex)); int err = netlink_send(nlmsg, sock); if (err < 0) { } } static void netlink_add_macvlan(struct nlmsg* nlmsg, int sock, const char* name, const char* link) { netlink_add_device_impl(nlmsg, "macvlan", name); netlink_nest(nlmsg, IFLA_INFO_DATA); uint32_t mode = MACVLAN_MODE_BRIDGE; netlink_attr(nlmsg, IFLA_MACVLAN_MODE, &mode, sizeof(mode)); netlink_done(nlmsg); netlink_done(nlmsg); int ifindex = if_nametoindex(link); netlink_attr(nlmsg, IFLA_LINK, &ifindex, sizeof(ifindex)); int err = netlink_send(nlmsg, sock); if (err < 0) { } } static void netlink_add_geneve(struct nlmsg* nlmsg, int sock, const char* name, uint32_t vni, struct in_addr* addr4, struct in6_addr* addr6) { netlink_add_device_impl(nlmsg, "geneve", name); netlink_nest(nlmsg, IFLA_INFO_DATA); netlink_attr(nlmsg, IFLA_GENEVE_ID, &vni, sizeof(vni)); if (addr4) netlink_attr(nlmsg, IFLA_GENEVE_REMOTE, addr4, sizeof(*addr4)); if (addr6) netlink_attr(nlmsg, IFLA_GENEVE_REMOTE6, addr6, sizeof(*addr6)); netlink_done(nlmsg); netlink_done(nlmsg); int err = netlink_send(nlmsg, sock); if (err < 0) { } } #define IFLA_IPVLAN_FLAGS 2 #define IPVLAN_MODE_L3S 2 #undef IPVLAN_F_VEPA #define IPVLAN_F_VEPA 2 static void netlink_add_ipvlan(struct nlmsg* nlmsg, int sock, const char* name, const char* link, uint16_t mode, uint16_t flags) { netlink_add_device_impl(nlmsg, "ipvlan", name); netlink_nest(nlmsg, IFLA_INFO_DATA); netlink_attr(nlmsg, IFLA_IPVLAN_MODE, &mode, sizeof(mode)); netlink_attr(nlmsg, IFLA_IPVLAN_FLAGS, &flags, sizeof(flags)); netlink_done(nlmsg); netlink_done(nlmsg); int ifindex = if_nametoindex(link); netlink_attr(nlmsg, IFLA_LINK, &ifindex, sizeof(ifindex)); int err = netlink_send(nlmsg, sock); if (err < 0) { } } static void netlink_device_change(struct nlmsg* nlmsg, int sock, const char* name, bool up, const char* master, const void* mac, int macsize, const char* new_name) { struct ifinfomsg hdr; memset(&hdr, 0, sizeof(hdr)); if (up) hdr.ifi_flags = hdr.ifi_change = IFF_UP; hdr.ifi_index = if_nametoindex(name); netlink_init(nlmsg, RTM_NEWLINK, 0, &hdr, sizeof(hdr)); if (new_name) netlink_attr(nlmsg, IFLA_IFNAME, new_name, strlen(new_name)); if (master) { int ifindex = if_nametoindex(master); netlink_attr(nlmsg, IFLA_MASTER, &ifindex, sizeof(ifindex)); } if (macsize) netlink_attr(nlmsg, IFLA_ADDRESS, mac, macsize); int err = netlink_send(nlmsg, sock); if (err < 0) { } } static int netlink_add_addr(struct nlmsg* nlmsg, int sock, const char* dev, const void* addr, int addrsize) { struct ifaddrmsg hdr; memset(&hdr, 0, sizeof(hdr)); hdr.ifa_family = addrsize == 4 ? AF_INET : AF_INET6; hdr.ifa_prefixlen = addrsize == 4 ? 24 : 120; hdr.ifa_scope = RT_SCOPE_UNIVERSE; hdr.ifa_index = if_nametoindex(dev); netlink_init(nlmsg, RTM_NEWADDR, NLM_F_CREATE | NLM_F_REPLACE, &hdr, sizeof(hdr)); netlink_attr(nlmsg, IFA_LOCAL, addr, addrsize); netlink_attr(nlmsg, IFA_ADDRESS, addr, addrsize); return netlink_send(nlmsg, sock); } static void netlink_add_addr4(struct nlmsg* nlmsg, int sock, const char* dev, const char* addr) { struct in_addr in_addr; inet_pton(AF_INET, addr, &in_addr); int err = netlink_add_addr(nlmsg, sock, dev, &in_addr, sizeof(in_addr)); if (err < 0) { } } static void netlink_add_addr6(struct nlmsg* nlmsg, int sock, const char* dev, const char* addr) { struct in6_addr in6_addr; inet_pton(AF_INET6, addr, &in6_addr); int err = netlink_add_addr(nlmsg, sock, dev, &in6_addr, sizeof(in6_addr)); if (err < 0) { } } static void netlink_add_neigh(struct nlmsg* nlmsg, int sock, const char* name, const void* addr, int addrsize, const void* mac, int macsize) { struct ndmsg hdr; memset(&hdr, 0, sizeof(hdr)); hdr.ndm_family = addrsize == 4 ? AF_INET : AF_INET6; hdr.ndm_ifindex = if_nametoindex(name); hdr.ndm_state = NUD_PERMANENT; netlink_init(nlmsg, RTM_NEWNEIGH, NLM_F_EXCL | NLM_F_CREATE, &hdr, sizeof(hdr)); netlink_attr(nlmsg, NDA_DST, addr, addrsize); netlink_attr(nlmsg, NDA_LLADDR, mac, macsize); int err = netlink_send(nlmsg, sock); if (err < 0) { } } static struct nlmsg nlmsg; static int tunfd = -1; #define TUN_IFACE "syz_tun" #define LOCAL_MAC 0xaaaaaaaaaaaa #define REMOTE_MAC 0xaaaaaaaaaabb #define LOCAL_IPV4 "172.20.20.170" #define REMOTE_IPV4 "172.20.20.187" #define LOCAL_IPV6 "fe80::aa" #define REMOTE_IPV6 "fe80::bb" #define IFF_NAPI 0x0010 static void initialize_tun(void) { tunfd = open("/dev/net/tun", O_RDWR | O_NONBLOCK); if (tunfd == -1) { printf("tun: can't open /dev/net/tun: please enable CONFIG_TUN=y\n"); printf("otherwise fuzzing or reproducing might not work as intended\n"); return; } const int kTunFd = 200; if (dup2(tunfd, kTunFd) < 0) exit(1); close(tunfd); tunfd = kTunFd; struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, TUN_IFACE, IFNAMSIZ); ifr.ifr_flags = IFF_TAP | IFF_NO_PI; if (ioctl(tunfd, TUNSETIFF, (void*)&ifr) < 0) { exit(1); } char sysctl[64]; sprintf(sysctl, "/proc/sys/net/ipv6/conf/%s/accept_dad", TUN_IFACE); write_file(sysctl, "0"); sprintf(sysctl, "/proc/sys/net/ipv6/conf/%s/router_solicitations", TUN_IFACE); write_file(sysctl, "0"); int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (sock == -1) exit(1); netlink_add_addr4(&nlmsg, sock, TUN_IFACE, LOCAL_IPV4); netlink_add_addr6(&nlmsg, sock, TUN_IFACE, LOCAL_IPV6); uint64_t macaddr = REMOTE_MAC; struct in_addr in_addr; inet_pton(AF_INET, REMOTE_IPV4, &in_addr); netlink_add_neigh(&nlmsg, sock, TUN_IFACE, &in_addr, sizeof(in_addr), &macaddr, ETH_ALEN); struct in6_addr in6_addr; inet_pton(AF_INET6, REMOTE_IPV6, &in6_addr); netlink_add_neigh(&nlmsg, sock, TUN_IFACE, &in6_addr, sizeof(in6_addr), &macaddr, ETH_ALEN); macaddr = LOCAL_MAC; netlink_device_change(&nlmsg, sock, TUN_IFACE, true, 0, &macaddr, ETH_ALEN, NULL); close(sock); } #define DEVLINK_FAMILY_NAME "devlink" #define DEVLINK_CMD_PORT_GET 5 #define DEVLINK_ATTR_BUS_NAME 1 #define DEVLINK_ATTR_DEV_NAME 2 #define DEVLINK_ATTR_NETDEV_NAME 7 static struct nlmsg nlmsg2; static void initialize_devlink_ports(const char* bus_name, const char* dev_name, const char* netdev_prefix) { struct genlmsghdr genlhdr; int len, total_len, id, err, offset; uint16_t netdev_index; int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC); if (sock == -1) exit(1); int rtsock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (rtsock == -1) exit(1); id = netlink_query_family_id(&nlmsg, sock, DEVLINK_FAMILY_NAME, true); if (id == -1) goto error; memset(&genlhdr, 0, sizeof(genlhdr)); genlhdr.cmd = DEVLINK_CMD_PORT_GET; netlink_init(&nlmsg, id, NLM_F_DUMP, &genlhdr, sizeof(genlhdr)); netlink_attr(&nlmsg, DEVLINK_ATTR_BUS_NAME, bus_name, strlen(bus_name) + 1); netlink_attr(&nlmsg, DEVLINK_ATTR_DEV_NAME, dev_name, strlen(dev_name) + 1); err = netlink_send_ext(&nlmsg, sock, id, &total_len, true); if (err < 0) { goto error; } offset = 0; netdev_index = 0; while ((len = netlink_next_msg(&nlmsg, offset, total_len)) != -1) { struct nlattr* attr = (struct nlattr*)(nlmsg.buf + offset + NLMSG_HDRLEN + NLMSG_ALIGN(sizeof(genlhdr))); for (; (char*)attr < nlmsg.buf + offset + len; attr = (struct nlattr*)((char*)attr + NLMSG_ALIGN(attr->nla_len))) { if (attr->nla_type == DEVLINK_ATTR_NETDEV_NAME) { char* port_name; char netdev_name[IFNAMSIZ]; port_name = (char*)(attr + 1); snprintf(netdev_name, sizeof(netdev_name), "%s%d", netdev_prefix, netdev_index); netlink_device_change(&nlmsg2, rtsock, port_name, true, 0, 0, 0, netdev_name); break; } } offset += len; netdev_index++; } error: close(rtsock); close(sock); } #define DEV_IPV4 "172.20.20.%d" #define DEV_IPV6 "fe80::%02x" #define DEV_MAC 0x00aaaaaaaaaa static void netdevsim_add(unsigned int addr, unsigned int port_count) { char buf[16]; sprintf(buf, "%u %u", addr, port_count); if (write_file("/sys/bus/netdevsim/new_device", buf)) { snprintf(buf, sizeof(buf), "netdevsim%d", addr); initialize_devlink_ports("netdevsim", buf, "netdevsim"); } } #define WG_GENL_NAME "wireguard" enum wg_cmd { WG_CMD_GET_DEVICE, WG_CMD_SET_DEVICE, }; enum wgdevice_attribute { WGDEVICE_A_UNSPEC, WGDEVICE_A_IFINDEX, WGDEVICE_A_IFNAME, WGDEVICE_A_PRIVATE_KEY, WGDEVICE_A_PUBLIC_KEY, WGDEVICE_A_FLAGS, WGDEVICE_A_LISTEN_PORT, WGDEVICE_A_FWMARK, WGDEVICE_A_PEERS, }; enum wgpeer_attribute { WGPEER_A_UNSPEC, WGPEER_A_PUBLIC_KEY, WGPEER_A_PRESHARED_KEY, WGPEER_A_FLAGS, WGPEER_A_ENDPOINT, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, WGPEER_A_LAST_HANDSHAKE_TIME, WGPEER_A_RX_BYTES, WGPEER_A_TX_BYTES, WGPEER_A_ALLOWEDIPS, WGPEER_A_PROTOCOL_VERSION, }; enum wgallowedip_attribute { WGALLOWEDIP_A_UNSPEC, WGALLOWEDIP_A_FAMILY, WGALLOWEDIP_A_IPADDR, WGALLOWEDIP_A_CIDR_MASK, }; static void netlink_wireguard_setup(void) { const char ifname_a[] = "wg0"; const char ifname_b[] = "wg1"; const char ifname_c[] = "wg2"; const char private_a[] = "\xa0\x5c\xa8\x4f\x6c\x9c\x8e\x38\x53\xe2\xfd\x7a\x70\xae\x0f\xb2\x0f\xa1" "\x52\x60\x0c\xb0\x08\x45\x17\x4f\x08\x07\x6f\x8d\x78\x43"; const char private_b[] = "\xb0\x80\x73\xe8\xd4\x4e\x91\xe3\xda\x92\x2c\x22\x43\x82\x44\xbb\x88\x5c" "\x69\xe2\x69\xc8\xe9\xd8\x35\xb1\x14\x29\x3a\x4d\xdc\x6e"; const char private_c[] = "\xa0\xcb\x87\x9a\x47\xf5\xbc\x64\x4c\x0e\x69\x3f\xa6\xd0\x31\xc7\x4a\x15" "\x53\xb6\xe9\x01\xb9\xff\x2f\x51\x8c\x78\x04\x2f\xb5\x42"; const char public_a[] = "\x97\x5c\x9d\x81\xc9\x83\xc8\x20\x9e\xe7\x81\x25\x4b\x89\x9f\x8e\xd9\x25" "\xae\x9f\x09\x23\xc2\x3c\x62\xf5\x3c\x57\xcd\xbf\x69\x1c"; const char public_b[] = "\xd1\x73\x28\x99\xf6\x11\xcd\x89\x94\x03\x4d\x7f\x41\x3d\xc9\x57\x63\x0e" "\x54\x93\xc2\x85\xac\xa4\x00\x65\xcb\x63\x11\xbe\x69\x6b"; const char public_c[] = "\xf4\x4d\xa3\x67\xa8\x8e\xe6\x56\x4f\x02\x02\x11\x45\x67\x27\x08\x2f\x5c" "\xeb\xee\x8b\x1b\xf5\xeb\x73\x37\x34\x1b\x45\x9b\x39\x22"; const uint16_t listen_a = 20001; const uint16_t listen_b = 20002; const uint16_t listen_c = 20003; const uint16_t af_inet = AF_INET; const uint16_t af_inet6 = AF_INET6; const struct sockaddr_in endpoint_b_v4 = { .sin_family = AF_INET, .sin_port = htons(listen_b), .sin_addr = {htonl(INADDR_LOOPBACK)}}; const struct sockaddr_in endpoint_c_v4 = { .sin_family = AF_INET, .sin_port = htons(listen_c), .sin_addr = {htonl(INADDR_LOOPBACK)}}; struct sockaddr_in6 endpoint_a_v6 = {.sin6_family = AF_INET6, .sin6_port = htons(listen_a)}; endpoint_a_v6.sin6_addr = in6addr_loopback; struct sockaddr_in6 endpoint_c_v6 = {.sin6_family = AF_INET6, .sin6_port = htons(listen_c)}; endpoint_c_v6.sin6_addr = in6addr_loopback; const struct in_addr first_half_v4 = {0}; const struct in_addr second_half_v4 = {(uint32_t)htonl(128 << 24)}; const struct in6_addr first_half_v6 = {{{0}}}; const struct in6_addr second_half_v6 = {{{0x80}}}; const uint8_t half_cidr = 1; const uint16_t persistent_keepalives[] = {1, 3, 7, 9, 14, 19}; struct genlmsghdr genlhdr = {.cmd = WG_CMD_SET_DEVICE, .version = 1}; int sock; int id, err; sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC); if (sock == -1) { return; } id = netlink_query_family_id(&nlmsg, sock, WG_GENL_NAME, true); if (id == -1) goto error; netlink_init(&nlmsg, id, 0, &genlhdr, sizeof(genlhdr)); netlink_attr(&nlmsg, WGDEVICE_A_IFNAME, ifname_a, strlen(ifname_a) + 1); netlink_attr(&nlmsg, WGDEVICE_A_PRIVATE_KEY, private_a, 32); netlink_attr(&nlmsg, WGDEVICE_A_LISTEN_PORT, &listen_a, 2); netlink_nest(&nlmsg, NLA_F_NESTED | WGDEVICE_A_PEERS); netlink_nest(&nlmsg, NLA_F_NESTED | 0); netlink_attr(&nlmsg, WGPEER_A_PUBLIC_KEY, public_b, 32); netlink_attr(&nlmsg, WGPEER_A_ENDPOINT, &endpoint_b_v4, sizeof(endpoint_b_v4)); netlink_attr(&nlmsg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, &persistent_keepalives[0], 2); netlink_nest(&nlmsg, NLA_F_NESTED | WGPEER_A_ALLOWEDIPS); netlink_nest(&nlmsg, NLA_F_NESTED | 0); netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet, 2); netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &first_half_v4, sizeof(first_half_v4)); netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1); netlink_done(&nlmsg); netlink_nest(&nlmsg, NLA_F_NESTED | 0); netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet6, 2); netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &first_half_v6, sizeof(first_half_v6)); netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1); netlink_done(&nlmsg); netlink_done(&nlmsg); netlink_done(&nlmsg); netlink_nest(&nlmsg, NLA_F_NESTED | 0); netlink_attr(&nlmsg, WGPEER_A_PUBLIC_KEY, public_c, 32); netlink_attr(&nlmsg, WGPEER_A_ENDPOINT, &endpoint_c_v6, sizeof(endpoint_c_v6)); netlink_attr(&nlmsg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, &persistent_keepalives[1], 2); netlink_nest(&nlmsg, NLA_F_NESTED | WGPEER_A_ALLOWEDIPS); netlink_nest(&nlmsg, NLA_F_NESTED | 0); netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet, 2); netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &second_half_v4, sizeof(second_half_v4)); netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1); netlink_done(&nlmsg); netlink_nest(&nlmsg, NLA_F_NESTED | 0); netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet6, 2); netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &second_half_v6, sizeof(second_half_v6)); netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1); netlink_done(&nlmsg); netlink_done(&nlmsg); netlink_done(&nlmsg); netlink_done(&nlmsg); err = netlink_send(&nlmsg, sock); if (err < 0) { } netlink_init(&nlmsg, id, 0, &genlhdr, sizeof(genlhdr)); netlink_attr(&nlmsg, WGDEVICE_A_IFNAME, ifname_b, strlen(ifname_b) + 1); netlink_attr(&nlmsg, WGDEVICE_A_PRIVATE_KEY, private_b, 32); netlink_attr(&nlmsg, WGDEVICE_A_LISTEN_PORT, &listen_b, 2); netlink_nest(&nlmsg, NLA_F_NESTED | WGDEVICE_A_PEERS); netlink_nest(&nlmsg, NLA_F_NESTED | 0); netlink_attr(&nlmsg, WGPEER_A_PUBLIC_KEY, public_a, 32); netlink_attr(&nlmsg, WGPEER_A_ENDPOINT, &endpoint_a_v6, sizeof(endpoint_a_v6)); netlink_attr(&nlmsg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, &persistent_keepalives[2], 2); netlink_nest(&nlmsg, NLA_F_NESTED | WGPEER_A_ALLOWEDIPS); netlink_nest(&nlmsg, NLA_F_NESTED | 0); netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet, 2); netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &first_half_v4, sizeof(first_half_v4)); netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1); netlink_done(&nlmsg); netlink_nest(&nlmsg, NLA_F_NESTED | 0); netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet6, 2); netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &first_half_v6, sizeof(first_half_v6)); netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1); netlink_done(&nlmsg); netlink_done(&nlmsg); netlink_done(&nlmsg); netlink_nest(&nlmsg, NLA_F_NESTED | 0); netlink_attr(&nlmsg, WGPEER_A_PUBLIC_KEY, public_c, 32); netlink_attr(&nlmsg, WGPEER_A_ENDPOINT, &endpoint_c_v4, sizeof(endpoint_c_v4)); netlink_attr(&nlmsg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, &persistent_keepalives[3], 2); netlink_nest(&nlmsg, NLA_F_NESTED | WGPEER_A_ALLOWEDIPS); netlink_nest(&nlmsg, NLA_F_NESTED | 0); netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet, 2); netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &second_half_v4, sizeof(second_half_v4)); netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1); netlink_done(&nlmsg); netlink_nest(&nlmsg, NLA_F_NESTED | 0); netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet6, 2); netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &second_half_v6, sizeof(second_half_v6)); netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1); netlink_done(&nlmsg); netlink_done(&nlmsg); netlink_done(&nlmsg); netlink_done(&nlmsg); err = netlink_send(&nlmsg, sock); if (err < 0) { } netlink_init(&nlmsg, id, 0, &genlhdr, sizeof(genlhdr)); netlink_attr(&nlmsg, WGDEVICE_A_IFNAME, ifname_c, strlen(ifname_c) + 1); netlink_attr(&nlmsg, WGDEVICE_A_PRIVATE_KEY, private_c, 32); netlink_attr(&nlmsg, WGDEVICE_A_LISTEN_PORT, &listen_c, 2); netlink_nest(&nlmsg, NLA_F_NESTED | WGDEVICE_A_PEERS); netlink_nest(&nlmsg, NLA_F_NESTED | 0); netlink_attr(&nlmsg, WGPEER_A_PUBLIC_KEY, public_a, 32); netlink_attr(&nlmsg, WGPEER_A_ENDPOINT, &endpoint_a_v6, sizeof(endpoint_a_v6)); netlink_attr(&nlmsg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, &persistent_keepalives[4], 2); netlink_nest(&nlmsg, NLA_F_NESTED | WGPEER_A_ALLOWEDIPS); netlink_nest(&nlmsg, NLA_F_NESTED | 0); netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet, 2); netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &first_half_v4, sizeof(first_half_v4)); netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1); netlink_done(&nlmsg); netlink_nest(&nlmsg, NLA_F_NESTED | 0); netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet6, 2); netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &first_half_v6, sizeof(first_half_v6)); netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1); netlink_done(&nlmsg); netlink_done(&nlmsg); netlink_done(&nlmsg); netlink_nest(&nlmsg, NLA_F_NESTED | 0); netlink_attr(&nlmsg, WGPEER_A_PUBLIC_KEY, public_b, 32); netlink_attr(&nlmsg, WGPEER_A_ENDPOINT, &endpoint_b_v4, sizeof(endpoint_b_v4)); netlink_attr(&nlmsg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, &persistent_keepalives[5], 2); netlink_nest(&nlmsg, NLA_F_NESTED | WGPEER_A_ALLOWEDIPS); netlink_nest(&nlmsg, NLA_F_NESTED | 0); netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet, 2); netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &second_half_v4, sizeof(second_half_v4)); netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1); netlink_done(&nlmsg); netlink_nest(&nlmsg, NLA_F_NESTED | 0); netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet6, 2); netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &second_half_v6, sizeof(second_half_v6)); netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1); netlink_done(&nlmsg); netlink_done(&nlmsg); netlink_done(&nlmsg); netlink_done(&nlmsg); err = netlink_send(&nlmsg, sock); if (err < 0) { } error: close(sock); } static void initialize_netdevices(void) { char netdevsim[16]; sprintf(netdevsim, "netdevsim%d", (int)procid); struct { const char* type; const char* dev; } devtypes[] = { {"ip6gretap", "ip6gretap0"}, {"bridge", "bridge0"}, {"vcan", "vcan0"}, {"bond", "bond0"}, {"team", "team0"}, {"dummy", "dummy0"}, {"nlmon", "nlmon0"}, {"caif", "caif0"}, {"batadv", "batadv0"}, {"vxcan", "vxcan1"}, {"netdevsim", netdevsim}, {"veth", 0}, {"xfrm", "xfrm0"}, {"wireguard", "wg0"}, {"wireguard", "wg1"}, {"wireguard", "wg2"}, }; const char* devmasters[] = {"bridge", "bond", "team", "batadv"}; struct { const char* name; int macsize; bool noipv6; } devices[] = { {"lo", ETH_ALEN}, {"sit0", 0}, {"bridge0", ETH_ALEN}, {"vcan0", 0, true}, {"tunl0", 0}, {"gre0", 0}, {"gretap0", ETH_ALEN}, {"ip_vti0", 0}, {"ip6_vti0", 0}, {"ip6tnl0", 0}, {"ip6gre0", 0}, {"ip6gretap0", ETH_ALEN}, {"erspan0", ETH_ALEN}, {"bond0", ETH_ALEN}, {"veth0", ETH_ALEN}, {"veth1", ETH_ALEN}, {"team0", ETH_ALEN}, {"veth0_to_bridge", ETH_ALEN}, {"veth1_to_bridge", ETH_ALEN}, {"veth0_to_bond", ETH_ALEN}, {"veth1_to_bond", ETH_ALEN}, {"veth0_to_team", ETH_ALEN}, {"veth1_to_team", ETH_ALEN}, {"veth0_to_hsr", ETH_ALEN}, {"veth1_to_hsr", ETH_ALEN}, {"hsr0", 0}, {"dummy0", ETH_ALEN}, {"nlmon0", 0}, {"vxcan0", 0, true}, {"vxcan1", 0, true}, {"caif0", ETH_ALEN}, {"batadv0", ETH_ALEN}, {netdevsim, ETH_ALEN}, {"xfrm0", ETH_ALEN}, {"veth0_virt_wifi", ETH_ALEN}, {"veth1_virt_wifi", ETH_ALEN}, {"virt_wifi0", ETH_ALEN}, {"veth0_vlan", ETH_ALEN}, {"veth1_vlan", ETH_ALEN}, {"vlan0", ETH_ALEN}, {"vlan1", ETH_ALEN}, {"macvlan0", ETH_ALEN}, {"macvlan1", ETH_ALEN}, {"ipvlan0", ETH_ALEN}, {"ipvlan1", ETH_ALEN}, {"veth0_macvtap", ETH_ALEN}, {"veth1_macvtap", ETH_ALEN}, {"macvtap0", ETH_ALEN}, {"macsec0", ETH_ALEN}, {"veth0_to_batadv", ETH_ALEN}, {"veth1_to_batadv", ETH_ALEN}, {"batadv_slave_0", ETH_ALEN}, {"batadv_slave_1", ETH_ALEN}, {"geneve0", ETH_ALEN}, {"geneve1", ETH_ALEN}, {"wg0", 0}, {"wg1", 0}, {"wg2", 0}, }; int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (sock == -1) exit(1); unsigned i; for (i = 0; i < sizeof(devtypes) / sizeof(devtypes[0]); i++) netlink_add_device(&nlmsg, sock, devtypes[i].type, devtypes[i].dev); for (i = 0; i < sizeof(devmasters) / (sizeof(devmasters[0])); i++) { char master[32], slave0[32], veth0[32], slave1[32], veth1[32]; sprintf(slave0, "%s_slave_0", devmasters[i]); sprintf(veth0, "veth0_to_%s", devmasters[i]); netlink_add_veth(&nlmsg, sock, slave0, veth0); sprintf(slave1, "%s_slave_1", devmasters[i]); sprintf(veth1, "veth1_to_%s", devmasters[i]); netlink_add_veth(&nlmsg, sock, slave1, veth1); sprintf(master, "%s0", devmasters[i]); netlink_device_change(&nlmsg, sock, slave0, false, master, 0, 0, NULL); netlink_device_change(&nlmsg, sock, slave1, false, master, 0, 0, NULL); } netlink_device_change(&nlmsg, sock, "bridge_slave_0", true, 0, 0, 0, NULL); netlink_device_change(&nlmsg, sock, "bridge_slave_1", true, 0, 0, 0, NULL); netlink_add_veth(&nlmsg, sock, "hsr_slave_0", "veth0_to_hsr"); netlink_add_veth(&nlmsg, sock, "hsr_slave_1", "veth1_to_hsr"); netlink_add_hsr(&nlmsg, sock, "hsr0", "hsr_slave_0", "hsr_slave_1"); netlink_device_change(&nlmsg, sock, "hsr_slave_0", true, 0, 0, 0, NULL); netlink_device_change(&nlmsg, sock, "hsr_slave_1", true, 0, 0, 0, NULL); netlink_add_veth(&nlmsg, sock, "veth0_virt_wifi", "veth1_virt_wifi"); netlink_add_linked(&nlmsg, sock, "virt_wifi", "virt_wifi0", "veth1_virt_wifi"); netlink_add_veth(&nlmsg, sock, "veth0_vlan", "veth1_vlan"); netlink_add_vlan(&nlmsg, sock, "vlan0", "veth0_vlan", 0, htons(ETH_P_8021Q)); netlink_add_vlan(&nlmsg, sock, "vlan1", "veth0_vlan", 1, htons(ETH_P_8021AD)); netlink_add_macvlan(&nlmsg, sock, "macvlan0", "veth1_vlan"); netlink_add_macvlan(&nlmsg, sock, "macvlan1", "veth1_vlan"); netlink_add_ipvlan(&nlmsg, sock, "ipvlan0", "veth0_vlan", IPVLAN_MODE_L2, 0); netlink_add_ipvlan(&nlmsg, sock, "ipvlan1", "veth0_vlan", IPVLAN_MODE_L3S, IPVLAN_F_VEPA); netlink_add_veth(&nlmsg, sock, "veth0_macvtap", "veth1_macvtap"); netlink_add_linked(&nlmsg, sock, "macvtap", "macvtap0", "veth0_macvtap"); netlink_add_linked(&nlmsg, sock, "macsec", "macsec0", "veth1_macvtap"); char addr[32]; sprintf(addr, DEV_IPV4, 14 + 10); struct in_addr geneve_addr4; if (inet_pton(AF_INET, addr, &geneve_addr4) <= 0) exit(1); struct in6_addr geneve_addr6; if (inet_pton(AF_INET6, "fc00::01", &geneve_addr6) <= 0) exit(1); netlink_add_geneve(&nlmsg, sock, "geneve0", 0, &geneve_addr4, 0); netlink_add_geneve(&nlmsg, sock, "geneve1", 1, 0, &geneve_addr6); netdevsim_add((int)procid, 4); netlink_wireguard_setup(); for (i = 0; i < sizeof(devices) / (sizeof(devices[0])); i++) { char addr[32]; sprintf(addr, DEV_IPV4, i + 10); netlink_add_addr4(&nlmsg, sock, devices[i].name, addr); if (!devices[i].noipv6) { sprintf(addr, DEV_IPV6, i + 10); netlink_add_addr6(&nlmsg, sock, devices[i].name, addr); } uint64_t macaddr = DEV_MAC + ((i + 10ull) << 40); netlink_device_change(&nlmsg, sock, devices[i].name, true, 0, &macaddr, devices[i].macsize, NULL); } close(sock); } static void initialize_netdevices_init(void) { int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (sock == -1) exit(1); struct { const char* type; int macsize; bool noipv6; bool noup; } devtypes[] = { {"nr", 7, true}, {"rose", 5, true, true}, }; unsigned i; for (i = 0; i < sizeof(devtypes) / sizeof(devtypes[0]); i++) { char dev[32], addr[32]; sprintf(dev, "%s%d", devtypes[i].type, (int)procid); sprintf(addr, "172.30.%d.%d", i, (int)procid + 1); netlink_add_addr4(&nlmsg, sock, dev, addr); if (!devtypes[i].noipv6) { sprintf(addr, "fe88::%02x:%02x", i, (int)procid + 1); netlink_add_addr6(&nlmsg, sock, dev, addr); } int macsize = devtypes[i].macsize; uint64_t macaddr = 0xbbbbbb + ((unsigned long long)i << (8 * (macsize - 2))) + (procid << (8 * (macsize - 1))); netlink_device_change(&nlmsg, sock, dev, !devtypes[i].noup, 0, &macaddr, macsize, NULL); } close(sock); } #define BTPROTO_HCI 1 #define ACL_LINK 1 #define SCAN_PAGE 2 typedef struct { uint8_t b[6]; } __attribute__((packed)) bdaddr_t; #define HCI_COMMAND_PKT 1 #define HCI_EVENT_PKT 4 #define HCI_VENDOR_PKT 0xff struct hci_command_hdr { uint16_t opcode; uint8_t plen; } __attribute__((packed)); struct hci_event_hdr { uint8_t evt; uint8_t plen; } __attribute__((packed)); #define HCI_EV_CONN_COMPLETE 0x03 struct hci_ev_conn_complete { uint8_t status; uint16_t handle; bdaddr_t bdaddr; uint8_t link_type; uint8_t encr_mode; } __attribute__((packed)); #define HCI_EV_CONN_REQUEST 0x04 struct hci_ev_conn_request { bdaddr_t bdaddr; uint8_t dev_class[3]; uint8_t link_type; } __attribute__((packed)); #define HCI_EV_REMOTE_FEATURES 0x0b struct hci_ev_remote_features { uint8_t status; uint16_t handle; uint8_t features[8]; } __attribute__((packed)); #define HCI_EV_CMD_COMPLETE 0x0e struct hci_ev_cmd_complete { uint8_t ncmd; uint16_t opcode; } __attribute__((packed)); #define HCI_OP_WRITE_SCAN_ENABLE 0x0c1a #define HCI_OP_READ_BUFFER_SIZE 0x1005 struct hci_rp_read_buffer_size { uint8_t status; uint16_t acl_mtu; uint8_t sco_mtu; uint16_t acl_max_pkt; uint16_t sco_max_pkt; } __attribute__((packed)); #define HCI_OP_READ_BD_ADDR 0x1009 struct hci_rp_read_bd_addr { uint8_t status; bdaddr_t bdaddr; } __attribute__((packed)); #define HCI_EV_LE_META 0x3e struct hci_ev_le_meta { uint8_t subevent; } __attribute__((packed)); #define HCI_EV_LE_CONN_COMPLETE 0x01 struct hci_ev_le_conn_complete { uint8_t status; uint16_t handle; uint8_t role; uint8_t bdaddr_type; bdaddr_t bdaddr; uint16_t interval; uint16_t latency; uint16_t supervision_timeout; uint8_t clk_accurancy; } __attribute__((packed)); struct hci_dev_req { uint16_t dev_id; uint32_t dev_opt; }; struct vhci_vendor_pkt { uint8_t type; uint8_t opcode; uint16_t id; }; #define HCIDEVUP _IOW('H', 201, int) #define HCISETSCAN _IOW('H', 221, int) static int vhci_fd = -1; static void rfkill_unblock_all() { int fd = open("/dev/rfkill", O_WRONLY); if (fd < 0) exit(1); struct rfkill_event event = {0}; event.idx = 0; event.type = RFKILL_TYPE_ALL; event.op = RFKILL_OP_CHANGE_ALL; event.soft = 0; event.hard = 0; if (write(fd, &event, sizeof(event)) < 0) exit(1); close(fd); } static void hci_send_event_packet(int fd, uint8_t evt, void* data, size_t data_len) { struct iovec iv[3]; struct hci_event_hdr hdr; hdr.evt = evt; hdr.plen = data_len; uint8_t type = HCI_EVENT_PKT; iv[0].iov_base = &type; iv[0].iov_len = sizeof(type); iv[1].iov_base = &hdr; iv[1].iov_len = sizeof(hdr); iv[2].iov_base = data; iv[2].iov_len = data_len; if (writev(fd, iv, sizeof(iv) / sizeof(struct iovec)) < 0) exit(1); } static void hci_send_event_cmd_complete(int fd, uint16_t opcode, void* data, size_t data_len) { struct iovec iv[4]; struct hci_event_hdr hdr; hdr.evt = HCI_EV_CMD_COMPLETE; hdr.plen = sizeof(struct hci_ev_cmd_complete) + data_len; struct hci_ev_cmd_complete evt_hdr; evt_hdr.ncmd = 1; evt_hdr.opcode = opcode; uint8_t type = HCI_EVENT_PKT; iv[0].iov_base = &type; iv[0].iov_len = sizeof(type); iv[1].iov_base = &hdr; iv[1].iov_len = sizeof(hdr); iv[2].iov_base = &evt_hdr; iv[2].iov_len = sizeof(evt_hdr); iv[3].iov_base = data; iv[3].iov_len = data_len; if (writev(fd, iv, sizeof(iv) / sizeof(struct iovec)) < 0) exit(1); } static bool process_command_pkt(int fd, char* buf, ssize_t buf_size) { struct hci_command_hdr* hdr = (struct hci_command_hdr*)buf; if (buf_size < (ssize_t)sizeof(struct hci_command_hdr) || hdr->plen != buf_size - sizeof(struct hci_command_hdr)) exit(1); switch (hdr->opcode) { case HCI_OP_WRITE_SCAN_ENABLE: { uint8_t status = 0; hci_send_event_cmd_complete(fd, hdr->opcode, &status, sizeof(status)); return true; } case HCI_OP_READ_BD_ADDR: { struct hci_rp_read_bd_addr rp = {0}; rp.status = 0; memset(&rp.bdaddr, 0xaa, 6); hci_send_event_cmd_complete(fd, hdr->opcode, &rp, sizeof(rp)); return false; } case HCI_OP_READ_BUFFER_SIZE: { struct hci_rp_read_buffer_size rp = {0}; rp.status = 0; rp.acl_mtu = 1021; rp.sco_mtu = 96; rp.acl_max_pkt = 4; rp.sco_max_pkt = 6; hci_send_event_cmd_complete(fd, hdr->opcode, &rp, sizeof(rp)); return false; } } char dummy[0xf9] = {0}; hci_send_event_cmd_complete(fd, hdr->opcode, dummy, sizeof(dummy)); return false; } static void* event_thread(void* arg) { while (1) { char buf[1024] = {0}; ssize_t buf_size = read(vhci_fd, buf, sizeof(buf)); if (buf_size < 0) exit(1); if (buf_size > 0 && buf[0] == HCI_COMMAND_PKT) { if (process_command_pkt(vhci_fd, buf + 1, buf_size - 1)) break; } } return NULL; } #define HCI_HANDLE_1 200 #define HCI_HANDLE_2 201 static void initialize_vhci() { int hci_sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); if (hci_sock < 0) exit(1); vhci_fd = open("/dev/vhci", O_RDWR); if (vhci_fd == -1) exit(1); const int kVhciFd = 202; if (dup2(vhci_fd, kVhciFd) < 0) exit(1); close(vhci_fd); vhci_fd = kVhciFd; struct vhci_vendor_pkt vendor_pkt; if (read(vhci_fd, &vendor_pkt, sizeof(vendor_pkt)) != sizeof(vendor_pkt)) exit(1); if (vendor_pkt.type != HCI_VENDOR_PKT) exit(1); pthread_t th; if (pthread_create(&th, NULL, event_thread, NULL)) exit(1); int ret = ioctl(hci_sock, HCIDEVUP, vendor_pkt.id); if (ret) { if (errno == ERFKILL) { rfkill_unblock_all(); ret = ioctl(hci_sock, HCIDEVUP, vendor_pkt.id); } if (ret && errno != EALREADY) exit(1); } struct hci_dev_req dr = {0}; dr.dev_id = vendor_pkt.id; dr.dev_opt = SCAN_PAGE; if (ioctl(hci_sock, HCISETSCAN, &dr)) exit(1); struct hci_ev_conn_request request; memset(&request, 0, sizeof(request)); memset(&request.bdaddr, 0xaa, 6); *(uint8_t*)&request.bdaddr.b[5] = 0x10; request.link_type = ACL_LINK; hci_send_event_packet(vhci_fd, HCI_EV_CONN_REQUEST, &request, sizeof(request)); struct hci_ev_conn_complete complete; memset(&complete, 0, sizeof(complete)); complete.status = 0; complete.handle = HCI_HANDLE_1; memset(&complete.bdaddr, 0xaa, 6); *(uint8_t*)&complete.bdaddr.b[5] = 0x10; complete.link_type = ACL_LINK; complete.encr_mode = 0; hci_send_event_packet(vhci_fd, HCI_EV_CONN_COMPLETE, &complete, sizeof(complete)); struct hci_ev_remote_features features; memset(&features, 0, sizeof(features)); features.status = 0; features.handle = HCI_HANDLE_1; hci_send_event_packet(vhci_fd, HCI_EV_REMOTE_FEATURES, &features, sizeof(features)); struct { struct hci_ev_le_meta le_meta; struct hci_ev_le_conn_complete le_conn; } le_conn; memset(&le_conn, 0, sizeof(le_conn)); le_conn.le_meta.subevent = HCI_EV_LE_CONN_COMPLETE; memset(&le_conn.le_conn.bdaddr, 0xaa, 6); *(uint8_t*)&le_conn.le_conn.bdaddr.b[5] = 0x11; le_conn.le_conn.role = 1; le_conn.le_conn.handle = HCI_HANDLE_2; hci_send_event_packet(vhci_fd, HCI_EV_LE_META, &le_conn, sizeof(le_conn)); pthread_join(th, NULL); close(hci_sock); } #define ADDR_TEXT 0x0000 #define ADDR_GDT 0x1000 #define ADDR_LDT 0x1800 #define ADDR_PML4 0x2000 #define ADDR_PDP 0x3000 #define ADDR_PD 0x4000 #define ADDR_STACK0 0x0f80 #define ADDR_VAR_HLT 0x2800 #define ADDR_VAR_SYSRET 0x2808 #define ADDR_VAR_SYSEXIT 0x2810 #define ADDR_VAR_IDT 0x3800 #define ADDR_VAR_TSS64 0x3a00 #define ADDR_VAR_TSS64_CPL3 0x3c00 #define ADDR_VAR_TSS16 0x3d00 #define ADDR_VAR_TSS16_2 0x3e00 #define ADDR_VAR_TSS16_CPL3 0x3f00 #define ADDR_VAR_TSS32 0x4800 #define ADDR_VAR_TSS32_2 0x4a00 #define ADDR_VAR_TSS32_CPL3 0x4c00 #define ADDR_VAR_TSS32_VM86 0x4e00 #define ADDR_VAR_VMXON_PTR 0x5f00 #define ADDR_VAR_VMCS_PTR 0x5f08 #define ADDR_VAR_VMEXIT_PTR 0x5f10 #define ADDR_VAR_VMWRITE_FLD 0x5f18 #define ADDR_VAR_VMWRITE_VAL 0x5f20 #define ADDR_VAR_VMXON 0x6000 #define ADDR_VAR_VMCS 0x7000 #define ADDR_VAR_VMEXIT_CODE 0x9000 #define ADDR_VAR_USER_CODE 0x9100 #define ADDR_VAR_USER_CODE2 0x9120 #define SEL_LDT (1 << 3) #define SEL_CS16 (2 << 3) #define SEL_DS16 (3 << 3) #define SEL_CS16_CPL3 ((4 << 3) + 3) #define SEL_DS16_CPL3 ((5 << 3) + 3) #define SEL_CS32 (6 << 3) #define SEL_DS32 (7 << 3) #define SEL_CS32_CPL3 ((8 << 3) + 3) #define SEL_DS32_CPL3 ((9 << 3) + 3) #define SEL_CS64 (10 << 3) #define SEL_DS64 (11 << 3) #define SEL_CS64_CPL3 ((12 << 3) + 3) #define SEL_DS64_CPL3 ((13 << 3) + 3) #define SEL_CGATE16 (14 << 3) #define SEL_TGATE16 (15 << 3) #define SEL_CGATE32 (16 << 3) #define SEL_TGATE32 (17 << 3) #define SEL_CGATE64 (18 << 3) #define SEL_CGATE64_HI (19 << 3) #define SEL_TSS16 (20 << 3) #define SEL_TSS16_2 (21 << 3) #define SEL_TSS16_CPL3 ((22 << 3) + 3) #define SEL_TSS32 (23 << 3) #define SEL_TSS32_2 (24 << 3) #define SEL_TSS32_CPL3 ((25 << 3) + 3) #define SEL_TSS32_VM86 (26 << 3) #define SEL_TSS64 (27 << 3) #define SEL_TSS64_HI (28 << 3) #define SEL_TSS64_CPL3 ((29 << 3) + 3) #define SEL_TSS64_CPL3_HI (30 << 3) #define MSR_IA32_FEATURE_CONTROL 0x3a #define MSR_IA32_VMX_BASIC 0x480 #define MSR_IA32_SMBASE 0x9e #define MSR_IA32_SYSENTER_CS 0x174 #define MSR_IA32_SYSENTER_ESP 0x175 #define MSR_IA32_SYSENTER_EIP 0x176 #define MSR_IA32_STAR 0xC0000081 #define MSR_IA32_LSTAR 0xC0000082 #define MSR_IA32_VMX_PROCBASED_CTLS2 0x48B #define NEXT_INSN $0xbadc0de #define PREFIX_SIZE 0xba1d const char kvm_asm16_cpl3[] = "\x0f\x20\xc0\x66\x83\xc8\x01\x0f\x22\xc0\xb8\xa0\x00\x0f\x00\xd8\xb8\x2b" "\x00\x8e\xd8\x8e\xc0\x8e\xe0\x8e\xe8\xbc\x00\x01\xc7\x06\x00\x01\x1d\xba" "\xc7\x06\x02\x01\x23\x00\xc7\x06\x04\x01\x00\x01\xc7\x06\x06\x01\x2b\x00" "\xcb"; const char kvm_asm32_paged[] = "\x0f\x20\xc0\x0d\x00\x00\x00\x80\x0f\x22\xc0"; const char kvm_asm32_vm86[] = "\x66\xb8\xb8\x00\x0f\x00\xd8\xea\x00\x00\x00\x00\xd0\x00"; const char kvm_asm32_paged_vm86[] = "\x0f\x20\xc0\x0d\x00\x00\x00\x80\x0f\x22\xc0\x66\xb8\xb8\x00\x0f\x00\xd8" "\xea\x00\x00\x00\x00\xd0\x00"; const char kvm_asm64_enable_long[] = "\x0f\x20\xc0\x0d\x00\x00\x00\x80\x0f\x22\xc0\xea\xde\xc0\xad\x0b\x50\x00" "\x48\xc7\xc0\xd8\x00\x00\x00\x0f\x00\xd8"; const char kvm_asm64_init_vm[] = "\x0f\x20\xc0\x0d\x00\x00\x00\x80\x0f\x22\xc0\xea\xde\xc0\xad\x0b\x50\x00" "\x48\xc7\xc0\xd8\x00\x00\x00\x0f\x00\xd8\x48\xc7\xc1\x3a\x00\x00\x00\x0f" "\x32\x48\x83\xc8\x05\x0f\x30\x0f\x20\xe0\x48\x0d\x00\x20\x00\x00\x0f\x22" "\xe0\x48\xc7\xc1\x80\x04\x00\x00\x0f\x32\x48\xc7\xc2\x00\x60\x00\x00\x89" "\x02\x48\xc7\xc2\x00\x70\x00\x00\x89\x02\x48\xc7\xc0\x00\x5f\x00\x00\xf3" "\x0f\xc7\x30\x48\xc7\xc0\x08\x5f\x00\x00\x66\x0f\xc7\x30\x0f\xc7\x30\x48" "\xc7\xc1\x81\x04\x00\x00\x0f\x32\x48\x83\xc8\x00\x48\x21\xd0\x48\xc7\xc2" "\x00\x40\x00\x00\x0f\x79\xd0\x48\xc7\xc1\x82\x04\x00\x00\x0f\x32\x48\x83" "\xc8\x00\x48\x21\xd0\x48\xc7\xc2\x02\x40\x00\x00\x0f\x79\xd0\x48\xc7\xc2" "\x1e\x40\x00\x00\x48\xc7\xc0\x81\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc1\x83" "\x04\x00\x00\x0f\x32\x48\x0d\xff\x6f\x03\x00\x48\x21\xd0\x48\xc7\xc2\x0c" "\x40\x00\x00\x0f\x79\xd0\x48\xc7\xc1\x84\x04\x00\x00\x0f\x32\x48\x0d\xff" "\x17\x00\x00\x48\x21\xd0\x48\xc7\xc2\x12\x40\x00\x00\x0f\x79\xd0\x48\xc7" "\xc2\x04\x2c\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2" "\x00\x28\x00\x00\x48\xc7\xc0\xff\xff\xff\xff\x0f\x79\xd0\x48\xc7\xc2\x02" "\x0c\x00\x00\x48\xc7\xc0\x50\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc0\x58\x00" "\x00\x00\x48\xc7\xc2\x00\x0c\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x04\x0c\x00" "\x00\x0f\x79\xd0\x48\xc7\xc2\x06\x0c\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x08" "\x0c\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x0a\x0c\x00\x00\x0f\x79\xd0\x48\xc7" "\xc0\xd8\x00\x00\x00\x48\xc7\xc2\x0c\x0c\x00\x00\x0f\x79\xd0\x48\xc7\xc2" "\x02\x2c\x00\x00\x48\xc7\xc0\x00\x05\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x00" "\x4c\x00\x00\x48\xc7\xc0\x50\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x10\x6c" "\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x12\x6c\x00" "\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x0f\x20\xc0\x48\xc7\xc2\x00" "\x6c\x00\x00\x48\x89\xc0\x0f\x79\xd0\x0f\x20\xd8\x48\xc7\xc2\x02\x6c\x00" "\x00\x48\x89\xc0\x0f\x79\xd0\x0f\x20\xe0\x48\xc7\xc2\x04\x6c\x00\x00\x48" "\x89\xc0\x0f\x79\xd0\x48\xc7\xc2\x06\x6c\x00\x00\x48\xc7\xc0\x00\x00\x00" "\x00\x0f\x79\xd0\x48\xc7\xc2\x08\x6c\x00\x00\x48\xc7\xc0\x00\x00\x00\x00" "\x0f\x79\xd0\x48\xc7\xc2\x0a\x6c\x00\x00\x48\xc7\xc0\x00\x3a\x00\x00\x0f" "\x79\xd0\x48\xc7\xc2\x0c\x6c\x00\x00\x48\xc7\xc0\x00\x10\x00\x00\x0f\x79" "\xd0\x48\xc7\xc2\x0e\x6c\x00\x00\x48\xc7\xc0\x00\x38\x00\x00\x0f\x79\xd0" "\x48\xc7\xc2\x14\x6c\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48" "\xc7\xc2\x16\x6c\x00\x00\x48\x8b\x04\x25\x10\x5f\x00\x00\x0f\x79\xd0\x48" "\xc7\xc2\x00\x00\x00\x00\x48\xc7\xc0\x01\x00\x00\x00\x0f\x79\xd0\x48\xc7" "\xc2\x02\x00\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2" "\x00\x20\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x02" "\x20\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x04\x20" "\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x06\x20\x00" "\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc1\x77\x02\x00\x00" "\x0f\x32\x48\xc1\xe2\x20\x48\x09\xd0\x48\xc7\xc2\x00\x2c\x00\x00\x48\x89" "\xc0\x0f\x79\xd0\x48\xc7\xc2\x04\x40\x00\x00\x48\xc7\xc0\x00\x00\x00\x00" "\x0f\x79\xd0\x48\xc7\xc2\x0a\x40\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f" "\x79\xd0\x48\xc7\xc2\x0e\x40\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79" "\xd0\x48\xc7\xc2\x10\x40\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0" "\x48\xc7\xc2\x16\x40\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48" "\xc7\xc2\x14\x40\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7" "\xc2\x00\x60\x00\x00\x48\xc7\xc0\xff\xff\xff\xff\x0f\x79\xd0\x48\xc7\xc2" "\x02\x60\x00\x00\x48\xc7\xc0\xff\xff\xff\xff\x0f\x79\xd0\x48\xc7\xc2\x1c" "\x20\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x1e\x20" "\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x20\x20\x00" "\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x22\x20\x00\x00" "\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x00\x08\x00\x00\x48" "\xc7\xc0\x58\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x02\x08\x00\x00\x48\xc7" "\xc0\x50\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x04\x08\x00\x00\x48\xc7\xc0" "\x58\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x06\x08\x00\x00\x48\xc7\xc0\x58" "\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x08\x08\x00\x00\x48\xc7\xc0\x58\x00" "\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x0a\x08\x00\x00\x48\xc7\xc0\x58\x00\x00" "\x00\x0f\x79\xd0\x48\xc7\xc2\x0c\x08\x00\x00\x48\xc7\xc0\x00\x00\x00\x00" "\x0f\x79\xd0\x48\xc7\xc2\x0e\x08\x00\x00\x48\xc7\xc0\xd8\x00\x00\x00\x0f" "\x79\xd0\x48\xc7\xc2\x12\x68\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79" "\xd0\x48\xc7\xc2\x14\x68\x00\x00\x48\xc7\xc0\x00\x3a\x00\x00\x0f\x79\xd0" "\x48\xc7\xc2\x16\x68\x00\x00\x48\xc7\xc0\x00\x10\x00\x00\x0f\x79\xd0\x48" "\xc7\xc2\x18\x68\x00\x00\x48\xc7\xc0\x00\x38\x00\x00\x0f\x79\xd0\x48\xc7" "\xc2\x00\x48\x00\x00\x48\xc7\xc0\xff\xff\x0f\x00\x0f\x79\xd0\x48\xc7\xc2" "\x02\x48\x00\x00\x48\xc7\xc0\xff\xff\x0f\x00\x0f\x79\xd0\x48\xc7\xc2\x04" "\x48\x00\x00\x48\xc7\xc0\xff\xff\x0f\x00\x0f\x79\xd0\x48\xc7\xc2\x06\x48" "\x00\x00\x48\xc7\xc0\xff\xff\x0f\x00\x0f\x79\xd0\x48\xc7\xc2\x08\x48\x00" "\x00\x48\xc7\xc0\xff\xff\x0f\x00\x0f\x79\xd0\x48\xc7\xc2\x0a\x48\x00\x00" "\x48\xc7\xc0\xff\xff\x0f\x00\x0f\x79\xd0\x48\xc7\xc2\x0c\x48\x00\x00\x48" "\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x0e\x48\x00\x00\x48\xc7" "\xc0\xff\x1f\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x10\x48\x00\x00\x48\xc7\xc0" "\xff\x1f\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x12\x48\x00\x00\x48\xc7\xc0\xff" "\x1f\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x14\x48\x00\x00\x48\xc7\xc0\x93\x40" "\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x16\x48\x00\x00\x48\xc7\xc0\x9b\x20\x00" "\x00\x0f\x79\xd0\x48\xc7\xc2\x18\x48\x00\x00\x48\xc7\xc0\x93\x40\x00\x00" "\x0f\x79\xd0\x48\xc7\xc2\x1a\x48\x00\x00\x48\xc7\xc0\x93\x40\x00\x00\x0f" "\x79\xd0\x48\xc7\xc2\x1c\x48\x00\x00\x48\xc7\xc0\x93\x40\x00\x00\x0f\x79" "\xd0\x48\xc7\xc2\x1e\x48\x00\x00\x48\xc7\xc0\x93\x40\x00\x00\x0f\x79\xd0" "\x48\xc7\xc2\x20\x48\x00\x00\x48\xc7\xc0\x82\x00\x00\x00\x0f\x79\xd0\x48" "\xc7\xc2\x22\x48\x00\x00\x48\xc7\xc0\x8b\x00\x00\x00\x0f\x79\xd0\x48\xc7" "\xc2\x1c\x68\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2" "\x1e\x68\x00\x00\x48\xc7\xc0\x00\x91\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x20" "\x68\x00\x00\x48\xc7\xc0\x02\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x06\x28" "\x00\x00\x48\xc7\xc0\x00\x05\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x0a\x28\x00" "\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x0c\x28\x00\x00" "\x48\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x0e\x28\x00\x00\x48" "\xc7\xc0\x00\x00\x00\x00\x0f\x79\xd0\x48\xc7\xc2\x10\x28\x00\x00\x48\xc7" "\xc0\x00\x00\x00\x00\x0f\x79\xd0\x0f\x20\xc0\x48\xc7\xc2\x00\x68\x00\x00" "\x48\x89\xc0\x0f\x79\xd0\x0f\x20\xd8\x48\xc7\xc2\x02\x68\x00\x00\x48\x89" "\xc0\x0f\x79\xd0\x0f\x20\xe0\x48\xc7\xc2\x04\x68\x00\x00\x48\x89\xc0\x0f" "\x79\xd0\x48\xc7\xc0\x18\x5f\x00\x00\x48\x8b\x10\x48\xc7\xc0\x20\x5f\x00" "\x00\x48\x8b\x08\x48\x31\xc0\x0f\x78\xd0\x48\x31\xc8\x0f\x79\xd0\x0f\x01" "\xc2\x48\xc7\xc2\x00\x44\x00\x00\x0f\x78\xd0\xf4"; const char kvm_asm64_vm_exit[] = "\x48\xc7\xc3\x00\x44\x00\x00\x0f\x78\xda\x48\xc7\xc3\x02\x44\x00\x00\x0f" "\x78\xd9\x48\xc7\xc0\x00\x64\x00\x00\x0f\x78\xc0\x48\xc7\xc3\x1e\x68\x00" "\x00\x0f\x78\xdb\xf4"; const char kvm_asm64_cpl3[] = "\x0f\x20\xc0\x0d\x00\x00\x00\x80\x0f\x22\xc0\xea\xde\xc0\xad\x0b\x50\x00" "\x48\xc7\xc0\xd8\x00\x00\x00\x0f\x00\xd8\x48\xc7\xc0\x6b\x00\x00\x00\x8e" "\xd8\x8e\xc0\x8e\xe0\x8e\xe8\x48\xc7\xc4\x80\x0f\x00\x00\x48\xc7\x04\x24" "\x1d\xba\x00\x00\x48\xc7\x44\x24\x04\x63\x00\x00\x00\x48\xc7\x44\x24\x08" "\x80\x0f\x00\x00\x48\xc7\x44\x24\x0c\x6b\x00\x00\x00\xcb"; #define KVM_SMI _IO(KVMIO, 0xb7) #define CR0_PE 1 #define CR0_MP (1 << 1) #define CR0_EM (1 << 2) #define CR0_TS (1 << 3) #define CR0_ET (1 << 4) #define CR0_NE (1 << 5) #define CR0_WP (1 << 16) #define CR0_AM (1 << 18) #define CR0_NW (1 << 29) #define CR0_CD (1 << 30) #define CR0_PG (1 << 31) #define CR4_VME 1 #define CR4_PVI (1 << 1) #define CR4_TSD (1 << 2) #define CR4_DE (1 << 3) #define CR4_PSE (1 << 4) #define CR4_PAE (1 << 5) #define CR4_MCE (1 << 6) #define CR4_PGE (1 << 7) #define CR4_PCE (1 << 8) #define CR4_OSFXSR (1 << 8) #define CR4_OSXMMEXCPT (1 << 10) #define CR4_UMIP (1 << 11) #define CR4_VMXE (1 << 13) #define CR4_SMXE (1 << 14) #define CR4_FSGSBASE (1 << 16) #define CR4_PCIDE (1 << 17) #define CR4_OSXSAVE (1 << 18) #define CR4_SMEP (1 << 20) #define CR4_SMAP (1 << 21) #define CR4_PKE (1 << 22) #define EFER_SCE 1 #define EFER_LME (1 << 8) #define EFER_LMA (1 << 10) #define EFER_NXE (1 << 11) #define EFER_SVME (1 << 12) #define EFER_LMSLE (1 << 13) #define EFER_FFXSR (1 << 14) #define EFER_TCE (1 << 15) #define PDE32_PRESENT 1 #define PDE32_RW (1 << 1) #define PDE32_USER (1 << 2) #define PDE32_PS (1 << 7) #define PDE64_PRESENT 1 #define PDE64_RW (1 << 1) #define PDE64_USER (1 << 2) #define PDE64_ACCESSED (1 << 5) #define PDE64_DIRTY (1 << 6) #define PDE64_PS (1 << 7) #define PDE64_G (1 << 8) struct tss16 { uint16_t prev; uint16_t sp0; uint16_t ss0; uint16_t sp1; uint16_t ss1; uint16_t sp2; uint16_t ss2; uint16_t ip; uint16_t flags; uint16_t ax; uint16_t cx; uint16_t dx; uint16_t bx; uint16_t sp; uint16_t bp; uint16_t si; uint16_t di; uint16_t es; uint16_t cs; uint16_t ss; uint16_t ds; uint16_t ldt; } __attribute__((packed)); struct tss32 { uint16_t prev, prevh; uint32_t sp0; uint16_t ss0, ss0h; uint32_t sp1; uint16_t ss1, ss1h; uint32_t sp2; uint16_t ss2, ss2h; uint32_t cr3; uint32_t ip; uint32_t flags; uint32_t ax; uint32_t cx; uint32_t dx; uint32_t bx; uint32_t sp; uint32_t bp; uint32_t si; uint32_t di; uint16_t es, esh; uint16_t cs, csh; uint16_t ss, ssh; uint16_t ds, dsh; uint16_t fs, fsh; uint16_t gs, gsh; uint16_t ldt, ldth; uint16_t trace; uint16_t io_bitmap; } __attribute__((packed)); struct tss64 { uint32_t reserved0; uint64_t rsp[3]; uint64_t reserved1; uint64_t ist[7]; uint64_t reserved2; uint32_t reserved3; uint32_t io_bitmap; } __attribute__((packed)); static void fill_segment_descriptor(uint64_t* dt, uint64_t* lt, struct kvm_segment* seg) { uint16_t index = seg->selector >> 3; uint64_t limit = seg->g ? seg->limit >> 12 : seg->limit; uint64_t sd = (limit & 0xffff) | (seg->base & 0xffffff) << 16 | (uint64_t)seg->type << 40 | (uint64_t)seg->s << 44 | (uint64_t)seg->dpl << 45 | (uint64_t)seg->present << 47 | (limit & 0xf0000ULL) << 48 | (uint64_t)seg->avl << 52 | (uint64_t)seg->l << 53 | (uint64_t)seg->db << 54 | (uint64_t)seg->g << 55 | (seg->base & 0xff000000ULL) << 56; dt[index] = sd; lt[index] = sd; } static void fill_segment_descriptor_dword(uint64_t* dt, uint64_t* lt, struct kvm_segment* seg) { fill_segment_descriptor(dt, lt, seg); uint16_t index = seg->selector >> 3; dt[index + 1] = 0; lt[index + 1] = 0; } static void setup_syscall_msrs(int cpufd, uint16_t sel_cs, uint16_t sel_cs_cpl3) { char buf[sizeof(struct kvm_msrs) + 5 * sizeof(struct kvm_msr_entry)]; memset(buf, 0, sizeof(buf)); struct kvm_msrs* msrs = (struct kvm_msrs*)buf; struct kvm_msr_entry* entries = msrs->entries; msrs->nmsrs = 5; entries[0].index = MSR_IA32_SYSENTER_CS; entries[0].data = sel_cs; entries[1].index = MSR_IA32_SYSENTER_ESP; entries[1].data = ADDR_STACK0; entries[2].index = MSR_IA32_SYSENTER_EIP; entries[2].data = ADDR_VAR_SYSEXIT; entries[3].index = MSR_IA32_STAR; entries[3].data = ((uint64_t)sel_cs << 32) | ((uint64_t)sel_cs_cpl3 << 48); entries[4].index = MSR_IA32_LSTAR; entries[4].data = ADDR_VAR_SYSRET; ioctl(cpufd, KVM_SET_MSRS, msrs); } static void setup_32bit_idt(struct kvm_sregs* sregs, char* host_mem, uintptr_t guest_mem) { sregs->idt.base = guest_mem + ADDR_VAR_IDT; sregs->idt.limit = 0x1ff; uint64_t* idt = (uint64_t*)(host_mem + sregs->idt.base); for (int i = 0; i < 32; i++) { struct kvm_segment gate; gate.selector = i << 3; switch (i % 6) { case 0: gate.type = 6; gate.base = SEL_CS16; break; case 1: gate.type = 7; gate.base = SEL_CS16; break; case 2: gate.type = 3; gate.base = SEL_TGATE16; break; case 3: gate.type = 14; gate.base = SEL_CS32; break; case 4: gate.type = 15; gate.base = SEL_CS32; break; case 5: gate.type = 11; gate.base = SEL_TGATE32; break; } gate.limit = guest_mem + ADDR_VAR_USER_CODE2; gate.present = 1; gate.dpl = 0; gate.s = 0; gate.g = 0; gate.db = 0; gate.l = 0; gate.avl = 0; fill_segment_descriptor(idt, idt, &gate); } } static void setup_64bit_idt(struct kvm_sregs* sregs, char* host_mem, uintptr_t guest_mem) { sregs->idt.base = guest_mem + ADDR_VAR_IDT; sregs->idt.limit = 0x1ff; uint64_t* idt = (uint64_t*)(host_mem + sregs->idt.base); for (int i = 0; i < 32; i++) { struct kvm_segment gate; gate.selector = (i * 2) << 3; gate.type = (i & 1) ? 14 : 15; gate.base = SEL_CS64; gate.limit = guest_mem + ADDR_VAR_USER_CODE2; gate.present = 1; gate.dpl = 0; gate.s = 0; gate.g = 0; gate.db = 0; gate.l = 0; gate.avl = 0; fill_segment_descriptor_dword(idt, idt, &gate); } } struct kvm_text { uintptr_t typ; const void* text; uintptr_t size; }; struct kvm_opt { uint64_t typ; uint64_t val; }; #define KVM_SETUP_PAGING (1 << 0) #define KVM_SETUP_PAE (1 << 1) #define KVM_SETUP_PROTECTED (1 << 2) #define KVM_SETUP_CPL3 (1 << 3) #define KVM_SETUP_VIRT86 (1 << 4) #define KVM_SETUP_SMM (1 << 5) #define KVM_SETUP_VM (1 << 6) static volatile long syz_kvm_setup_cpu(volatile long a0, volatile long a1, volatile long a2, volatile long a3, volatile long a4, volatile long a5, volatile long a6, volatile long a7) { const int vmfd = a0; const int cpufd = a1; char* const host_mem = (char*)a2; const struct kvm_text* const text_array_ptr = (struct kvm_text*)a3; const uintptr_t text_count = a4; const uintptr_t flags = a5; const struct kvm_opt* const opt_array_ptr = (struct kvm_opt*)a6; uintptr_t opt_count = a7; const uintptr_t page_size = 4 << 10; const uintptr_t ioapic_page = 10; const uintptr_t guest_mem_size = 24 * page_size; const uintptr_t guest_mem = 0; (void)text_count; int text_type = text_array_ptr[0].typ; const void* text = text_array_ptr[0].text; uintptr_t text_size = text_array_ptr[0].size; for (uintptr_t i = 0; i < guest_mem_size / page_size; i++) { struct kvm_userspace_memory_region memreg; memreg.slot = i; memreg.flags = 0; memreg.guest_phys_addr = guest_mem + i * page_size; if (i == ioapic_page) memreg.guest_phys_addr = 0xfec00000; memreg.memory_size = page_size; memreg.userspace_addr = (uintptr_t)host_mem + i * page_size; ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, &memreg); } struct kvm_userspace_memory_region memreg; memreg.slot = 1 + (1 << 16); memreg.flags = 0; memreg.guest_phys_addr = 0x30000; memreg.memory_size = 64 << 10; memreg.userspace_addr = (uintptr_t)host_mem; ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, &memreg); struct kvm_sregs sregs; if (ioctl(cpufd, KVM_GET_SREGS, &sregs)) return -1; struct kvm_regs regs; memset(®s, 0, sizeof(regs)); regs.rip = guest_mem + ADDR_TEXT; regs.rsp = ADDR_STACK0; sregs.gdt.base = guest_mem + ADDR_GDT; sregs.gdt.limit = 256 * sizeof(uint64_t) - 1; uint64_t* gdt = (uint64_t*)(host_mem + sregs.gdt.base); struct kvm_segment seg_ldt; seg_ldt.selector = SEL_LDT; seg_ldt.type = 2; seg_ldt.base = guest_mem + ADDR_LDT; seg_ldt.limit = 256 * sizeof(uint64_t) - 1; seg_ldt.present = 1; seg_ldt.dpl = 0; seg_ldt.s = 0; seg_ldt.g = 0; seg_ldt.db = 1; seg_ldt.l = 0; sregs.ldt = seg_ldt; uint64_t* ldt = (uint64_t*)(host_mem + sregs.ldt.base); struct kvm_segment seg_cs16; seg_cs16.selector = SEL_CS16; seg_cs16.type = 11; seg_cs16.base = 0; seg_cs16.limit = 0xfffff; seg_cs16.present = 1; seg_cs16.dpl = 0; seg_cs16.s = 1; seg_cs16.g = 0; seg_cs16.db = 0; seg_cs16.l = 0; struct kvm_segment seg_ds16 = seg_cs16; seg_ds16.selector = SEL_DS16; seg_ds16.type = 3; struct kvm_segment seg_cs16_cpl3 = seg_cs16; seg_cs16_cpl3.selector = SEL_CS16_CPL3; seg_cs16_cpl3.dpl = 3; struct kvm_segment seg_ds16_cpl3 = seg_ds16; seg_ds16_cpl3.selector = SEL_DS16_CPL3; seg_ds16_cpl3.dpl = 3; struct kvm_segment seg_cs32 = seg_cs16; seg_cs32.selector = SEL_CS32; seg_cs32.db = 1; struct kvm_segment seg_ds32 = seg_ds16; seg_ds32.selector = SEL_DS32; seg_ds32.db = 1; struct kvm_segment seg_cs32_cpl3 = seg_cs32; seg_cs32_cpl3.selector = SEL_CS32_CPL3; seg_cs32_cpl3.dpl = 3; struct kvm_segment seg_ds32_cpl3 = seg_ds32; seg_ds32_cpl3.selector = SEL_DS32_CPL3; seg_ds32_cpl3.dpl = 3; struct kvm_segment seg_cs64 = seg_cs16; seg_cs64.selector = SEL_CS64; seg_cs64.l = 1; struct kvm_segment seg_ds64 = seg_ds32; seg_ds64.selector = SEL_DS64; struct kvm_segment seg_cs64_cpl3 = seg_cs64; seg_cs64_cpl3.selector = SEL_CS64_CPL3; seg_cs64_cpl3.dpl = 3; struct kvm_segment seg_ds64_cpl3 = seg_ds64; seg_ds64_cpl3.selector = SEL_DS64_CPL3; seg_ds64_cpl3.dpl = 3; struct kvm_segment seg_tss32; seg_tss32.selector = SEL_TSS32; seg_tss32.type = 9; seg_tss32.base = ADDR_VAR_TSS32; seg_tss32.limit = 0x1ff; seg_tss32.present = 1; seg_tss32.dpl = 0; seg_tss32.s = 0; seg_tss32.g = 0; seg_tss32.db = 0; seg_tss32.l = 0; struct kvm_segment seg_tss32_2 = seg_tss32; seg_tss32_2.selector = SEL_TSS32_2; seg_tss32_2.base = ADDR_VAR_TSS32_2; struct kvm_segment seg_tss32_cpl3 = seg_tss32; seg_tss32_cpl3.selector = SEL_TSS32_CPL3; seg_tss32_cpl3.base = ADDR_VAR_TSS32_CPL3; struct kvm_segment seg_tss32_vm86 = seg_tss32; seg_tss32_vm86.selector = SEL_TSS32_VM86; seg_tss32_vm86.base = ADDR_VAR_TSS32_VM86; struct kvm_segment seg_tss16 = seg_tss32; seg_tss16.selector = SEL_TSS16; seg_tss16.base = ADDR_VAR_TSS16; seg_tss16.limit = 0xff; seg_tss16.type = 1; struct kvm_segment seg_tss16_2 = seg_tss16; seg_tss16_2.selector = SEL_TSS16_2; seg_tss16_2.base = ADDR_VAR_TSS16_2; seg_tss16_2.dpl = 0; struct kvm_segment seg_tss16_cpl3 = seg_tss16; seg_tss16_cpl3.selector = SEL_TSS16_CPL3; seg_tss16_cpl3.base = ADDR_VAR_TSS16_CPL3; seg_tss16_cpl3.dpl = 3; struct kvm_segment seg_tss64 = seg_tss32; seg_tss64.selector = SEL_TSS64; seg_tss64.base = ADDR_VAR_TSS64; seg_tss64.limit = 0x1ff; struct kvm_segment seg_tss64_cpl3 = seg_tss64; seg_tss64_cpl3.selector = SEL_TSS64_CPL3; seg_tss64_cpl3.base = ADDR_VAR_TSS64_CPL3; seg_tss64_cpl3.dpl = 3; struct kvm_segment seg_cgate16; seg_cgate16.selector = SEL_CGATE16; seg_cgate16.type = 4; seg_cgate16.base = SEL_CS16 | (2 << 16); seg_cgate16.limit = ADDR_VAR_USER_CODE2; seg_cgate16.present = 1; seg_cgate16.dpl = 0; seg_cgate16.s = 0; seg_cgate16.g = 0; seg_cgate16.db = 0; seg_cgate16.l = 0; seg_cgate16.avl = 0; struct kvm_segment seg_tgate16 = seg_cgate16; seg_tgate16.selector = SEL_TGATE16; seg_tgate16.type = 3; seg_cgate16.base = SEL_TSS16_2; seg_tgate16.limit = 0; struct kvm_segment seg_cgate32 = seg_cgate16; seg_cgate32.selector = SEL_CGATE32; seg_cgate32.type = 12; seg_cgate32.base = SEL_CS32 | (2 << 16); struct kvm_segment seg_tgate32 = seg_cgate32; seg_tgate32.selector = SEL_TGATE32; seg_tgate32.type = 11; seg_tgate32.base = SEL_TSS32_2; seg_tgate32.limit = 0; struct kvm_segment seg_cgate64 = seg_cgate16; seg_cgate64.selector = SEL_CGATE64; seg_cgate64.type = 12; seg_cgate64.base = SEL_CS64; int kvmfd = open("/dev/kvm", O_RDWR); char buf[sizeof(struct kvm_cpuid2) + 128 * sizeof(struct kvm_cpuid_entry2)]; memset(buf, 0, sizeof(buf)); struct kvm_cpuid2* cpuid = (struct kvm_cpuid2*)buf; cpuid->nent = 128; ioctl(kvmfd, KVM_GET_SUPPORTED_CPUID, cpuid); ioctl(cpufd, KVM_SET_CPUID2, cpuid); close(kvmfd); const char* text_prefix = 0; int text_prefix_size = 0; char* host_text = host_mem + ADDR_TEXT; if (text_type == 8) { if (flags & KVM_SETUP_SMM) { if (flags & KVM_SETUP_PROTECTED) { sregs.cs = seg_cs16; sregs.ds = sregs.es = sregs.fs = sregs.gs = sregs.ss = seg_ds16; sregs.cr0 |= CR0_PE; } else { sregs.cs.selector = 0; sregs.cs.base = 0; } *(host_mem + ADDR_TEXT) = 0xf4; host_text = host_mem + 0x8000; ioctl(cpufd, KVM_SMI, 0); } else if (flags & KVM_SETUP_VIRT86) { sregs.cs = seg_cs32; sregs.ds = sregs.es = sregs.fs = sregs.gs = sregs.ss = seg_ds32; sregs.cr0 |= CR0_PE; sregs.efer |= EFER_SCE; setup_syscall_msrs(cpufd, SEL_CS32, SEL_CS32_CPL3); setup_32bit_idt(&sregs, host_mem, guest_mem); if (flags & KVM_SETUP_PAGING) { uint64_t pd_addr = guest_mem + ADDR_PD; uint64_t* pd = (uint64_t*)(host_mem + ADDR_PD); pd[0] = PDE32_PRESENT | PDE32_RW | PDE32_USER | PDE32_PS; sregs.cr3 = pd_addr; sregs.cr4 |= CR4_PSE; text_prefix = kvm_asm32_paged_vm86; text_prefix_size = sizeof(kvm_asm32_paged_vm86) - 1; } else { text_prefix = kvm_asm32_vm86; text_prefix_size = sizeof(kvm_asm32_vm86) - 1; } } else { sregs.cs.selector = 0; sregs.cs.base = 0; } } else if (text_type == 16) { if (flags & KVM_SETUP_CPL3) { sregs.cs = seg_cs16; sregs.ds = sregs.es = sregs.fs = sregs.gs = sregs.ss = seg_ds16; text_prefix = kvm_asm16_cpl3; text_prefix_size = sizeof(kvm_asm16_cpl3) - 1; } else { sregs.cr0 |= CR0_PE; sregs.cs = seg_cs16; sregs.ds = sregs.es = sregs.fs = sregs.gs = sregs.ss = seg_ds16; } } else if (text_type == 32) { sregs.cr0 |= CR0_PE; sregs.efer |= EFER_SCE; setup_syscall_msrs(cpufd, SEL_CS32, SEL_CS32_CPL3); setup_32bit_idt(&sregs, host_mem, guest_mem); if (flags & KVM_SETUP_SMM) { sregs.cs = seg_cs32; sregs.ds = sregs.es = sregs.fs = sregs.gs = sregs.ss = seg_ds32; *(host_mem + ADDR_TEXT) = 0xf4; host_text = host_mem + 0x8000; ioctl(cpufd, KVM_SMI, 0); } else if (flags & KVM_SETUP_PAGING) { sregs.cs = seg_cs32; sregs.ds = sregs.es = sregs.fs = sregs.gs = sregs.ss = seg_ds32; uint64_t pd_addr = guest_mem + ADDR_PD; uint64_t* pd = (uint64_t*)(host_mem + ADDR_PD); pd[0] = PDE32_PRESENT | PDE32_RW | PDE32_USER | PDE32_PS; sregs.cr3 = pd_addr; sregs.cr4 |= CR4_PSE; text_prefix = kvm_asm32_paged; text_prefix_size = sizeof(kvm_asm32_paged) - 1; } else if (flags & KVM_SETUP_CPL3) { sregs.cs = seg_cs32_cpl3; sregs.ds = sregs.es = sregs.fs = sregs.gs = sregs.ss = seg_ds32_cpl3; } else { sregs.cs = seg_cs32; sregs.ds = sregs.es = sregs.fs = sregs.gs = sregs.ss = seg_ds32; } } else { sregs.efer |= EFER_LME | EFER_SCE; sregs.cr0 |= CR0_PE; setup_syscall_msrs(cpufd, SEL_CS64, SEL_CS64_CPL3); setup_64bit_idt(&sregs, host_mem, guest_mem); sregs.cs = seg_cs32; sregs.ds = sregs.es = sregs.fs = sregs.gs = sregs.ss = seg_ds32; uint64_t pml4_addr = guest_mem + ADDR_PML4; uint64_t* pml4 = (uint64_t*)(host_mem + ADDR_PML4); uint64_t pdpt_addr = guest_mem + ADDR_PDP; uint64_t* pdpt = (uint64_t*)(host_mem + ADDR_PDP); uint64_t pd_addr = guest_mem + ADDR_PD; uint64_t* pd = (uint64_t*)(host_mem + ADDR_PD); pml4[0] = PDE64_PRESENT | PDE64_RW | PDE64_USER | pdpt_addr; pdpt[0] = PDE64_PRESENT | PDE64_RW | PDE64_USER | pd_addr; pd[0] = PDE64_PRESENT | PDE64_RW | PDE64_USER | PDE64_PS; sregs.cr3 = pml4_addr; sregs.cr4 |= CR4_PAE; if (flags & KVM_SETUP_VM) { sregs.cr0 |= CR0_NE; *((uint64_t*)(host_mem + ADDR_VAR_VMXON_PTR)) = ADDR_VAR_VMXON; *((uint64_t*)(host_mem + ADDR_VAR_VMCS_PTR)) = ADDR_VAR_VMCS; memcpy(host_mem + ADDR_VAR_VMEXIT_CODE, kvm_asm64_vm_exit, sizeof(kvm_asm64_vm_exit) - 1); *((uint64_t*)(host_mem + ADDR_VAR_VMEXIT_PTR)) = ADDR_VAR_VMEXIT_CODE; text_prefix = kvm_asm64_init_vm; text_prefix_size = sizeof(kvm_asm64_init_vm) - 1; } else if (flags & KVM_SETUP_CPL3) { text_prefix = kvm_asm64_cpl3; text_prefix_size = sizeof(kvm_asm64_cpl3) - 1; } else { text_prefix = kvm_asm64_enable_long; text_prefix_size = sizeof(kvm_asm64_enable_long) - 1; } } struct tss16 tss16; memset(&tss16, 0, sizeof(tss16)); tss16.ss0 = tss16.ss1 = tss16.ss2 = SEL_DS16; tss16.sp0 = tss16.sp1 = tss16.sp2 = ADDR_STACK0; tss16.ip = ADDR_VAR_USER_CODE2; tss16.flags = (1 << 1); tss16.cs = SEL_CS16; tss16.es = tss16.ds = tss16.ss = SEL_DS16; tss16.ldt = SEL_LDT; struct tss16* tss16_addr = (struct tss16*)(host_mem + seg_tss16_2.base); memcpy(tss16_addr, &tss16, sizeof(tss16)); memset(&tss16, 0, sizeof(tss16)); tss16.ss0 = tss16.ss1 = tss16.ss2 = SEL_DS16; tss16.sp0 = tss16.sp1 = tss16.sp2 = ADDR_STACK0; tss16.ip = ADDR_VAR_USER_CODE2; tss16.flags = (1 << 1); tss16.cs = SEL_CS16_CPL3; tss16.es = tss16.ds = tss16.ss = SEL_DS16_CPL3; tss16.ldt = SEL_LDT; struct tss16* tss16_cpl3_addr = (struct tss16*)(host_mem + seg_tss16_cpl3.base); memcpy(tss16_cpl3_addr, &tss16, sizeof(tss16)); struct tss32 tss32; memset(&tss32, 0, sizeof(tss32)); tss32.ss0 = tss32.ss1 = tss32.ss2 = SEL_DS32; tss32.sp0 = tss32.sp1 = tss32.sp2 = ADDR_STACK0; tss32.ip = ADDR_VAR_USER_CODE; tss32.flags = (1 << 1) | (1 << 17); tss32.ldt = SEL_LDT; tss32.cr3 = sregs.cr3; tss32.io_bitmap = offsetof(struct tss32, io_bitmap); struct tss32* tss32_addr = (struct tss32*)(host_mem + seg_tss32_vm86.base); memcpy(tss32_addr, &tss32, sizeof(tss32)); memset(&tss32, 0, sizeof(tss32)); tss32.ss0 = tss32.ss1 = tss32.ss2 = SEL_DS32; tss32.sp0 = tss32.sp1 = tss32.sp2 = ADDR_STACK0; tss32.ip = ADDR_VAR_USER_CODE; tss32.flags = (1 << 1); tss32.cr3 = sregs.cr3; tss32.es = tss32.ds = tss32.ss = tss32.gs = tss32.fs = SEL_DS32; tss32.cs = SEL_CS32; tss32.ldt = SEL_LDT; tss32.cr3 = sregs.cr3; tss32.io_bitmap = offsetof(struct tss32, io_bitmap); struct tss32* tss32_cpl3_addr = (struct tss32*)(host_mem + seg_tss32_2.base); memcpy(tss32_cpl3_addr, &tss32, sizeof(tss32)); struct tss64 tss64; memset(&tss64, 0, sizeof(tss64)); tss64.rsp[0] = ADDR_STACK0; tss64.rsp[1] = ADDR_STACK0; tss64.rsp[2] = ADDR_STACK0; tss64.io_bitmap = offsetof(struct tss64, io_bitmap); struct tss64* tss64_addr = (struct tss64*)(host_mem + seg_tss64.base); memcpy(tss64_addr, &tss64, sizeof(tss64)); memset(&tss64, 0, sizeof(tss64)); tss64.rsp[0] = ADDR_STACK0; tss64.rsp[1] = ADDR_STACK0; tss64.rsp[2] = ADDR_STACK0; tss64.io_bitmap = offsetof(struct tss64, io_bitmap); struct tss64* tss64_cpl3_addr = (struct tss64*)(host_mem + seg_tss64_cpl3.base); memcpy(tss64_cpl3_addr, &tss64, sizeof(tss64)); if (text_size > 1000) text_size = 1000; if (text_prefix) { memcpy(host_text, text_prefix, text_prefix_size); void* patch = memmem(host_text, text_prefix_size, "\xde\xc0\xad\x0b", 4); if (patch) *((uint32_t*)patch) = guest_mem + ADDR_TEXT + ((char*)patch - host_text) + 6; uint16_t magic = PREFIX_SIZE; patch = memmem(host_text, text_prefix_size, &magic, sizeof(magic)); if (patch) *((uint16_t*)patch) = guest_mem + ADDR_TEXT + text_prefix_size; } memcpy((void*)(host_text + text_prefix_size), text, text_size); *(host_text + text_prefix_size + text_size) = 0xf4; memcpy(host_mem + ADDR_VAR_USER_CODE, text, text_size); *(host_mem + ADDR_VAR_USER_CODE + text_size) = 0xf4; *(host_mem + ADDR_VAR_HLT) = 0xf4; memcpy(host_mem + ADDR_VAR_SYSRET, "\x0f\x07\xf4", 3); memcpy(host_mem + ADDR_VAR_SYSEXIT, "\x0f\x35\xf4", 3); *(uint64_t*)(host_mem + ADDR_VAR_VMWRITE_FLD) = 0; *(uint64_t*)(host_mem + ADDR_VAR_VMWRITE_VAL) = 0; if (opt_count > 2) opt_count = 2; for (uintptr_t i = 0; i < opt_count; i++) { uint64_t typ = opt_array_ptr[i].typ; uint64_t val = opt_array_ptr[i].val; switch (typ % 9) { case 0: sregs.cr0 ^= val & (CR0_MP | CR0_EM | CR0_ET | CR0_NE | CR0_WP | CR0_AM | CR0_NW | CR0_CD); break; case 1: sregs.cr4 ^= val & (CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_MCE | CR4_PGE | CR4_PCE | CR4_OSFXSR | CR4_OSXMMEXCPT | CR4_UMIP | CR4_VMXE | CR4_SMXE | CR4_FSGSBASE | CR4_PCIDE | CR4_OSXSAVE | CR4_SMEP | CR4_SMAP | CR4_PKE); break; case 2: sregs.efer ^= val & (EFER_SCE | EFER_NXE | EFER_SVME | EFER_LMSLE | EFER_FFXSR | EFER_TCE); break; case 3: val &= ((1 << 8) | (1 << 9) | (1 << 10) | (1 << 12) | (1 << 13) | (1 << 14) | (1 << 15) | (1 << 18) | (1 << 19) | (1 << 20) | (1 << 21)); regs.rflags ^= val; tss16_addr->flags ^= val; tss16_cpl3_addr->flags ^= val; tss32_addr->flags ^= val; tss32_cpl3_addr->flags ^= val; break; case 4: seg_cs16.type = val & 0xf; seg_cs32.type = val & 0xf; seg_cs64.type = val & 0xf; break; case 5: seg_cs16_cpl3.type = val & 0xf; seg_cs32_cpl3.type = val & 0xf; seg_cs64_cpl3.type = val & 0xf; break; case 6: seg_ds16.type = val & 0xf; seg_ds32.type = val & 0xf; seg_ds64.type = val & 0xf; break; case 7: seg_ds16_cpl3.type = val & 0xf; seg_ds32_cpl3.type = val & 0xf; seg_ds64_cpl3.type = val & 0xf; break; case 8: *(uint64_t*)(host_mem + ADDR_VAR_VMWRITE_FLD) = (val & 0xffff); *(uint64_t*)(host_mem + ADDR_VAR_VMWRITE_VAL) = (val >> 16); break; default: exit(1); } } regs.rflags |= 2; fill_segment_descriptor(gdt, ldt, &seg_ldt); fill_segment_descriptor(gdt, ldt, &seg_cs16); fill_segment_descriptor(gdt, ldt, &seg_ds16); fill_segment_descriptor(gdt, ldt, &seg_cs16_cpl3); fill_segment_descriptor(gdt, ldt, &seg_ds16_cpl3); fill_segment_descriptor(gdt, ldt, &seg_cs32); fill_segment_descriptor(gdt, ldt, &seg_ds32); fill_segment_descriptor(gdt, ldt, &seg_cs32_cpl3); fill_segment_descriptor(gdt, ldt, &seg_ds32_cpl3); fill_segment_descriptor(gdt, ldt, &seg_cs64); fill_segment_descriptor(gdt, ldt, &seg_ds64); fill_segment_descriptor(gdt, ldt, &seg_cs64_cpl3); fill_segment_descriptor(gdt, ldt, &seg_ds64_cpl3); fill_segment_descriptor(gdt, ldt, &seg_tss32); fill_segment_descriptor(gdt, ldt, &seg_tss32_2); fill_segment_descriptor(gdt, ldt, &seg_tss32_cpl3); fill_segment_descriptor(gdt, ldt, &seg_tss32_vm86); fill_segment_descriptor(gdt, ldt, &seg_tss16); fill_segment_descriptor(gdt, ldt, &seg_tss16_2); fill_segment_descriptor(gdt, ldt, &seg_tss16_cpl3); fill_segment_descriptor_dword(gdt, ldt, &seg_tss64); fill_segment_descriptor_dword(gdt, ldt, &seg_tss64_cpl3); fill_segment_descriptor(gdt, ldt, &seg_cgate16); fill_segment_descriptor(gdt, ldt, &seg_tgate16); fill_segment_descriptor(gdt, ldt, &seg_cgate32); fill_segment_descriptor(gdt, ldt, &seg_tgate32); fill_segment_descriptor_dword(gdt, ldt, &seg_cgate64); if (ioctl(cpufd, KVM_SET_SREGS, &sregs)) return -1; if (ioctl(cpufd, KVM_SET_REGS, ®s)) return -1; return 0; } static void setup_common() { if (mount(0, "/sys/fs/fuse/connections", "fusectl", 0, 0)) { } } static void setup_binderfs() { if (mkdir("/dev/binderfs", 0777)) { } if (mount("binder", "/dev/binderfs", "binder", 0, NULL)) { } } static void loop(); static void sandbox_common() { prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); setsid(); struct rlimit rlim; rlim.rlim_cur = rlim.rlim_max = (200 << 20); setrlimit(RLIMIT_AS, &rlim); rlim.rlim_cur = rlim.rlim_max = 32 << 20; setrlimit(RLIMIT_MEMLOCK, &rlim); rlim.rlim_cur = rlim.rlim_max = 136 << 20; setrlimit(RLIMIT_FSIZE, &rlim); rlim.rlim_cur = rlim.rlim_max = 1 << 20; setrlimit(RLIMIT_STACK, &rlim); rlim.rlim_cur = rlim.rlim_max = 0; setrlimit(RLIMIT_CORE, &rlim); rlim.rlim_cur = rlim.rlim_max = 256; setrlimit(RLIMIT_NOFILE, &rlim); if (unshare(CLONE_NEWNS)) { } if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL)) { } if (unshare(CLONE_NEWIPC)) { } if (unshare(0x02000000)) { } if (unshare(CLONE_NEWUTS)) { } if (unshare(CLONE_SYSVSEM)) { } typedef struct { const char* name; const char* value; } sysctl_t; static const sysctl_t sysctls[] = { {"/proc/sys/kernel/shmmax", "16777216"}, {"/proc/sys/kernel/shmall", "536870912"}, {"/proc/sys/kernel/shmmni", "1024"}, {"/proc/sys/kernel/msgmax", "8192"}, {"/proc/sys/kernel/msgmni", "1024"}, {"/proc/sys/kernel/msgmnb", "1024"}, {"/proc/sys/kernel/sem", "1024 1048576 500 1024"}, }; unsigned i; for (i = 0; i < sizeof(sysctls) / sizeof(sysctls[0]); i++) write_file(sysctls[i].name, sysctls[i].value); } static int wait_for_loop(int pid) { if (pid < 0) exit(1); int status = 0; while (waitpid(-1, &status, __WALL) != pid) { } return WEXITSTATUS(status); } static void drop_caps(void) { struct __user_cap_header_struct cap_hdr = {}; struct __user_cap_data_struct cap_data[2] = {}; cap_hdr.version = _LINUX_CAPABILITY_VERSION_3; cap_hdr.pid = getpid(); if (syscall(SYS_capget, &cap_hdr, &cap_data)) exit(1); const int drop = (1 << CAP_SYS_PTRACE) | (1 << CAP_SYS_NICE); cap_data[0].effective &= ~drop; cap_data[0].permitted &= ~drop; cap_data[0].inheritable &= ~drop; if (syscall(SYS_capset, &cap_hdr, &cap_data)) exit(1); } static int do_sandbox_none(void) { if (unshare(CLONE_NEWPID)) { } int pid = fork(); if (pid != 0) return wait_for_loop(pid); setup_common(); initialize_vhci(); sandbox_common(); drop_caps(); initialize_netdevices_init(); if (unshare(CLONE_NEWNET)) { } initialize_tun(); initialize_netdevices(); setup_binderfs(); loop(); exit(1); } struct thread_t { int created, call; event_t ready, done; }; static struct thread_t threads[16]; static void execute_call(int call); static int running; static void* thr(void* arg) { struct thread_t* th = (struct thread_t*)arg; for (;;) { event_wait(&th->ready); event_reset(&th->ready); execute_call(th->call); __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED); event_set(&th->done); } return 0; } static void loop(void) { int i, call, thread; for (call = 0; call < 8; call++) { for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0])); thread++) { struct thread_t* th = &threads[thread]; if (!th->created) { th->created = 1; event_init(&th->ready); event_init(&th->done); event_set(&th->done); thread_start(thr, th); } if (!event_isset(&th->done)) continue; event_reset(&th->done); th->call = call; __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED); event_set(&th->ready); event_timedwait(&th->done, 50); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } uint64_t r[3] = {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}; void execute_call(int call) { intptr_t res = 0; switch (call) { case 0: memcpy((void*)0x20000000, "/dev/kvm\000", 9); res = syscall(__NR_openat, 0xffffffffffffff9cul, 0x20000000ul, 0ul, 0ul); if (res != -1) r[0] = res; break; case 1: res = syscall(__NR_ioctl, r[0], 0xae01, 0ul); if (res != -1) r[1] = res; break; case 2: res = syscall(__NR_ioctl, r[1], 0xae41, 0ul); if (res != -1) r[2] = res; break; case 3: *(uint32_t*)0x20000180 = 0; *(uint32_t*)0x20000184 = 2; *(uint64_t*)0x20000188 = 0; *(uint64_t*)0x20000190 = 0x2000; *(uint64_t*)0x20000198 = 0x20000000; syscall(__NR_ioctl, r[1], 0x4020ae46, 0x20000180ul); break; case 4: *(uint64_t*)0x200000c0 = 0x40; *(uint64_t*)0x200000c8 = 0; *(uint64_t*)0x200000d0 = 0; syz_kvm_setup_cpu(r[1], r[2], 0x20000000, 0x200000c0, 1, 0, 0, 0); break; case 5: *(uint32_t*)0x20000400 = -1; memcpy( (void*)0x20000408, "\x5f\xb2\xa2\x20\x8e\xbc\xbb\xd7\x91\xd9\x21\x47\x16\x25\x29\x24\x61" "\x0f\xfa\xf7\x58\x57\xcf\xfc\xd2\xbd\xfa\x32\x79\x0c\x8c\xea\x9f\x87" "\xfc\xed\x5c\x4d\x47\xcf\xf9\xf5\x4d\xb9\x7f\x3c\x26\x4d\x2c\x61\xc5" "\x0c\x42\xf7\x37\x65\x79\xec\x54\xf6\x93\x29\x99\x3e\xbb\xb7\x2a\x1c" "\x12\x28\x86\x4b\x79\xd0\x5b\xbf\xcb\xb5\x4b\xe2\x9c\x45\x17\xce\x92" "\x56\xab\xc9\x16\xa2\xb5\x24\x5e\xbe\x13\x3d\xa2\xd9\x9d\x18\x1e\x88" "\xce\x34\x92\x24\xe8\x39\x81\xea\x86\x65\x8e\x5d\xca\xa4\x5e\xc1\x03" "\x3e\x44\x22\x45\x8e\x80\xb3\xdf\x51\x90\x76\x58\x70\x4f\xa3\xbf\x87" "\x28\xa8\x52\x75\xf1\xfb\x7a\x98\x73\xc8\x3d\xde\x0f\x87\xdf\x75\x79" "\x41\xda\x3f\x80\xee\x79\x76\x90\x8d\x01\xad\xcc\x89\x91\xff\x13\xeb" "\xff\xd6\x1a\x5f\x9f\xb9\x4c\xf6\x7e\x25\xf8\x79\xa7\xe1\x5b\x44\xb3" "\xe2\x64\x2c\xb6\xff\xf4\xdb\x98\x84\x52\xea\xbc\xab\x6a\x6b\x8c\xae" "\xd3\xe7\x05\xde\x60\xc8\xe0\x4e\x8a\x78\x05\xf0\x89\x34\xab\xcb\x8b" "\x46\xb0\x8f\x42\xba\xad\x77\xe3\x90\xf0\x18\x80\x49\x74\x01\x95\x16" "\xb9\x58\x8b\x08\xc7\xd6\x96\x6c\xea\x54\x71\x33\xc9\x46\x40\x72\xb8" "\x92\x6b\x87\x7b\x52\x3d\x2a\xb3\x4a\x14\xf2\xeb\x6d\xdd\x8f\x18\x50" "\x36\xde\xd3\x49\x50\x59\xc8\x74\xf2\x62\xdd\x6e\x34\xb1\x1e\x60\x57" "\x68\x76\xa4\x1a\xf0\xb2\xe0\x15\xa9\x97\x15\x5f\xed\xd6\x18\x22\xaa" "\xd1\x92\x8d\x03\x8e\x16\x64\x64\xae\x88\xe4\x42\x0a\x79\x6e\x55\xa8" "\xf6\xaa\x64\x50\x3e\xc3\x2a\x6e\x20\x78\x0c\x38\xc8\x67\x90\x71\xa2" "\xa1\xea\x3e\xf2\x20\x59\xa1\x9e\x7d\x8a\x00\x19\x63\xc5\x74\xf4\x72" "\x6d\x8b\x15\x2c\x72\x4e\x55\x0d\x76\xba\xfd\x64\x6b\x6f\xd8\xb8\x1e" "\x56\x0b\x75\xc9\xaa\x1f\x34\xb8\x04\xf7\x75\x12\x63\xe4\x08\x30\x20" "\xed\xad\x76\x89\x82\x5b\xfb\xd3\x35\xef\x57\x56\xa0\xe7\x33\x1d\xc6" "\x90\x5e\xd3\x9e\xcf\x85\x6b\x96\x13\x01\x47\xec\xe5\x7e\xe1\xe1\xdc" "\xf6\xf7\x60\x59\xe8\x53\x4a\x38\x34\x4f\x12\xa8\x4e\x83\x9b\x07\x1c" "\xbb\x13\xd4\x0f\xe2\x21\xe8\x9e\x05\xe1\xfd\xdf\x0a\x2b\x76\x07\x1d" "\xfb\x30\x7f\x99\xac\xa3\xe4\x84\xc2\x44\x87\x61\x70\x0c\xb5\xa7\xac" "\xb1\x10\xe1\x34\x05\x2b\xba\x02\xd6\x40\x83\x43\x4b\xc8\x74\x95\xc2" "\x78\x93\xc5\x73\xe2\x5a\x0e\xa9\xce\x26\xef\xc3\xea\xad\x32\x7a\xb6" "\xaf\x05\x18\x2d\x98\x04\x54\x31\x43\x36\x7e\xf8\x99\xba\x44\x3c\xc3" "\x34\xe2\x04\x92\xb1\x14\x9f\x0f\xe2\x70\x60\x5e\x98\x5b\x2f\x60\x25" "\x91\xde\xe0\x5d\xe0\x3a\xc7\x50\xbc\xee\xbe\x5a\x79\x83\x3a\x19\x63" "\x72\xae\x6f\xd0\x36\x27\xaa\x22\x36\xee\xdb\x15\x36\x85\x33\x18\x6a" "\x1e\x0c\xef\xc1\x44\x7e\x2f\x0e\xb8\xdd\x2d\xec\x9a\x8c\x66\x95\x51" "\x0d\xa0\xcb\xd8\x6a\xee\x60\x46\x95\x67\xcf\xdd\x98\x7a\x0a\xb0\x00" "\x5e\x5d\xc2\xd0\xcc\x41\xa1\xb7\xc4\xa7\xae\x61\x29\x5e\xbd\xcc\x4b" "\x41\x69\x5e\xd2\x27\xa5\xc7\x62\x9a\x61\x5a\x85\x60\x59\xcb\x25\xff" "\xee\x4f\x00\xc2\x83\x29\x5c\x5b\x06\x30\x59\x3b\x1f\xa6\xdc\x40\x96" "\x9a\xd9\x01\x6c\x1d\xab\xf5\x39\x8e\xed\x1a\x74\x68\xc8\x6e\x7e\x96" "\x96\xec\x1d\x9e\x53\x1a\x67\x08\xdb\x2a\xd0\xd9\x43\x90\x48\xf8\x83" "\x92\x1b\x56\x1f\x6c\x25\xf5\x23\xd6\x4d\x6e\x9a\x76\x82\x15\xc0\xef" "\x56\x3d\xfd\x5a\x75\x71\x7f\xb3\x43\x63\xa3\x00\x1e\x4f\x4e\xbb\x95" "\x9d\xae\x10\xd1\x29\x23\xfb\x54\xd4\x66\x03\x0e\x8a\x18\x5e\x2a\x98" "\xa7\x2c\xa8\x55\xfd\x43\x0a\xca\x89\xb6\xb5\xfd\x85\x25\x08\xf5\x83" "\x3c\xef\x24\x53\x75\x8f\x27\x97\x3b\xce\x39\xda\xc2\xc0\xc7\x92\x1a" "\x70\xfc\xfb\x96\x52\x90\x7d\xfc\x13\x9e\x7b\x32\xdb\xfe\xe6\xfb\x3b" "\xb7\x0f\x7b\x88\xe4\x9b\xd0\x4b\x79\x4e\xfc\x0f\x31\x80\x60\x0e\xc0" "\xee\x72\x2c\x6b\xd5\xe6\x2b\x51\x84\x68\xb9\x49\xa1\x2a\x13\x7c\xd3" "\x11\xea\x92\xff\xc1\x4e\xa8\xf3\x96\x38\x84\xf1\xcf\x8f\x10\x3c\xe0" "\x41\xb5\x79\xd9\x16\xb6\xb2\xf9\x54\xf9\x50\xe6\x7f\x06\x14\xe1\xe7" "\x8f\x37\x53\x16\xec\x5c\xda\xcd\x24\x25\x80\x20\x13\x77\x4e\x53\x00" "\x59\x27\xd1\xb4\x32\xa9\xb0\xd5\x68\xe2\x07\x06\xca\x9f\x02\xd8\xbc" "\xfe\x21\x7f\x07\x6a\x3c\x05\xb5\x38\xb2\x83\x05\x57\xf3\xe6\xce\xb3" "\x15\x53\xb4\xaf\x4b\x67\x6c\x66\xd5\x74\x86\x01\x31\xc9\x0a\x2c\x7f" "\x5a\xc4\x47\x22\xe5\x29\xe4\xbd\xa1\x1f\x5f\xbc\x15\x53\x07\x60\x9e" "\xf0\x38\x8b\x9b\x29\x53\x34\xcb\xcd\x4f\x1e\x42\x47\xce\xa5\x75\x6b" "\xd2\xe7\x28\xcd\xda\x6a\x8a\x60\x93\xaf\x05\x8c\xf0\x81\xf8\xde\x6b" "\x0f\x8b\xf6\x02\x52\xea\x83\xe3\x98\x4c\x94\xc4\xed\xcb\xc5\xd7\x3e" "\xf1\x99\x82\x46\xc1\x81\x79\x9c\x3c\x07\x83\xca\x9f\xe8\xec\xfc\xfa" "\x1d\x12\xc2\xbb\x56\x44\x30\xef\x48\x6b\x97\x91\xf3\x7d\x86\x61\xde" "\xd7\x86\x28\x59\xa2\x87\x37\x76\x1b\xd6\xd5\x56\x95\xd5\x95\xd7\x75" "\x3c\x59\x9a\x00\x78\x4f\x70\x88\x27\x8a\xa6\x98\x2d\x0c\x7d\x80\xa8" "\xde\x9c\x94\x3d\xcd\x6c\xfc\x41\x57\x2f\xf5\xa8\xc1\x41\x61\x95\x13" "\xec\xa9\x75\x03\xab\x59\x29\x76\x19\xf9\xfe\x7c\xc2\x34\xef\x86\x5f" "\x2e\x1f\x93\x61\x25\xb0\x12\x92\xa1\xc9\xb3\x3b\xa1\xd4\xa7\x3e\xd4" "\xe4\x95\xe7\xbd\x10\x94\xae\x4b\xb3\x99\x35\x13\x1b\x61\x0a\xa6\x92" "\xfb\x2f\x46\x36\x86\x4d\xbb\x72\x29\x53\x85\xa6\xb2\xf2\x58\xac\x34" "\x3b\x21\x77\x8e\xa2\xf0\x04\x29\x59\xa3\xfc\x6b\x79\x79\x0f\xd3\x0e" "\xe4\xa8\x44\xb5\xf6\x46\x52\x3b\x3a\x6c\xcb\xee\x23\x64\xe2\xa7\x13" "\x32\x45\x61\x6c\x8c\x79\x54\x07\xf3\x3b\x09\xd8\x0e\xd1\x95\xe2\x97" "\x6e\xba\x0b\xdd\x8a\xb4\x06\x7d\x38\xac\xcf\x60\x1a\x73\x15\xd7\x2c" "\xe0\x91\xf0\x4f\x42\xd8\xb5\x5d\x2a\x8a\x1b\x6a\x84\xb1\x2d\x78\x9c" "\x11\x9a\x49\xc2\x2e\x35\xf0\xeb\xb9\x5e\xd5\x05\x7b\x40\x82\xbb\x61" "\x94\x6b\xe6\xfc\x32\xab\x25\xa3\x89\x74\x8c\x2b\x5e\xc6\xcc\x31\xf4" "\xea\xe6\xd3\x11\x33\xdb\xf5\xe2\x64\xaa\x85\x1a\x61\x8c\x05\x8b\x50" "\x14\x85\x1a\x9e\xe6\x27\x1e\x73\x7f\x90\x63\x1b\x23\x0e\xd3\xa6\xcd" "\x04\xcc\xaa\xfe\xa6\x11\x22\xae\xf9\x30\x97\xc5\xac\xd3\xd3\xef\x4c" "\xe6\xbb\x0d\xdd\x64\x1c\x4f\x8e\xd7\x76\x46\x3c\x36\xdc\x1c\x4e\xaa" "\xcb\xda\xf0\x68\xa3\xd1\x7a\x87\x5a\xb5\x59\x8e\x4f\xed\xea\xb7\x92" "\x57\xf6\x73\xfe\xb9\x60\x56\xaf\x9c\x21\xee\x82\xb8\xb2\x59\x43\xfb" "\xee\x55\xb7\xce\x2f\x5f\x8a\xd5\x53\x69\x5c\xcd\xab\x9e\xd0\x3e\x90" "\x65\x62\x91\xfa\x5c\x8b\xc7\x8a\x49\x9a\x95\x70\xcb\x2b\xdc\x92\x8b" "\x2e\xcc\x7a\xbf\x85\x82\x5c\xed\xf3\x8a\x61\x46\x95\x24\x1f\xc3\x81" "\x1a\x66\x72\xfc\xf7\x5c\x3a\xa5\x54\x6c\x20\xcf\x7c\x63\x0b\x0e\x94" "\x5d\x8c\x9c\xdb\xee\x7a\x38\x21\xca\x4b\xa8\xac\x2f\xd9\xdd\xbc\xbe" "\xc9\xe5\x3e\xb6\x65\xdc\x5f\xd3\x0d\x07\x1d\xf1\x67\x46\x25\xab\xcf" "\xf3\x48\x87\x2f\x02\x0a\xd4\x1a\xf4\x87\xff\xd0\xba\x42\x44\xca\x0a" "\xd6\x90\x67\x59\x31\x4a\xde\x7f\xfd\x2c\x63\xd8\x68\xa6\x30\x34\xe2" "\xd8\x16\x4f\x82\x75\xb2\x3a\x47\xdf\xa0\x2d\x89\x1b\xce\xf4\x31\x06" "\xc9\x01\xd2\xbc\x71\xb9\xad\x57\x6c\x93\xa1\x0c\x85\x22\x0e\xef\x17" "\x1e\xcf\xa3\x75\x30\x93\x97\x0b\x35\x6c\x0b\x24\x0a\x9a\x17\xa1\xb4" "\xa3\x48\x51\xe8\xed\x04\x6a\x65\x41\x25\x05\xce\xed\x0b\x36\xa0\x81" "\x37\x8e\x2d\x3d\xad\xac\x9d\x13\x2f\xf1\x0e\x02\xd4\x37\xca\xd5\x42" "\x36\x69\x9e\xa5\x2a\xf8\xe0\x3c\x59\x9d\x4d\x84\x2d\xd0\x5f\x62\x0f" "\x2c\x45\x76\x2c\x6f\x26\x9b\x1a\x6f\x46\xb2\x53\xab\x62\xb0\xa5\x0e" "\xd7\x87\xe6\xbb\x69\x50\xf2\x49\x2c\x23\x82\xcc\x59\x3f\xda\xb2\xe5" "\x83\x26\xcb\xd2\xa5\x04\xb5\x20\xab\xe8\x40\xd1\x09\x05\x39\xd1\xb7" "\xdf\xd5\xea\xb9\x84\x02\x23\xf5\x96\xc7\x1a\x3d\x4e\x67\xbf\x19\x5f" "\xf7\x2b\x0e\xd1\xee\x7a\x2b\x1d\x2f\x55\x1f\x75\x32\x3e\x9a\x22\x6e" "\xdb\x44\xdd\x8b\xf5\xf5\xd8\xfc\xda\x43\xf3\x7f\xfd\x9c\xf7\x6c\x34" "\x44\x6f\x1f\x3d\xa4\xa1\xb5\xd9\xf6\x72\x89\x7d\x90\xc5\xc0\x9a\xcc" "\x52\x78\x30\xf1\x4f\x9a\xf0\x7a\x35\x17\xae\xaf\xed\x96\x8d\x5c\x31" "\x1d\xaf\xba\xb0\x83\x87\xb1\x86\x0d\x4c\x33\x34\x0b\xdb\xb9\xd2\x6c" "\xfb\xda\xba\xc0\xfc\x2e\xb5\x58\xf8\x0c\x00\x71\xbc\x11\xea\xe6\x2a" "\x28\x2b\x51\x89\xef\x40\xa1\x5e\xab\xc2\x48\x40\xbc\x60\x30\x61\xbe" "\x7f\x1d\x09\xc5\xf7\x7a\x91\xbc\x29\x01\x76\x38\x7a\x3f\x2e\xeb\x79" "\xcb\x24\x4c\xdb\x21\x00\xf3\xb2\x7f\x4a\x44\x37\x04\x9c\x8a\x66\xe3" "\x8c\x58\xa5\x7b\x73\x09\x6f\xee\x16\x6e\x9d\xa1\xdf\x87\x54\xf9\xcf" "\xb6\x28\x7a\xe7\x9c\x83\xb2\x19\x54\xb1\xac\x70\x97\x3f\x1e\xc7\x08" "\xed\x5c\x0d\x27\x19\xb7\x24\x3e\x03\x26\xcf\x42\x6f\x13\xa3\x70\x96" "\xea\x22\x27\xdb\xd7\xf5\x41\xfd\xa7\x75\xd1\x02\x68\x31\x7d\x4e\x8b" "\x35\xf5\xfa\x66\x4c\xcd\x6c\x16\x57\x00\xca\x50\xd0\x25\xea\xd8\x59" "\xf7\xa6\xd4\xc4\x02\x3d\xc9\x61\xf4\x7f\xd8\x8c\xb7\xc4\x12\x17\x35" "\xd3\x2e\x64\xc2\x2f\xca\x3e\x5a\xd1\xb2\x16\xc5\x09\x29\x58\x27\xbd" "\x30\x72\xb2\x68\x87\x48\x09\x7b\x0b\x19\x0c\xb2\xcc\x29\xb1\x98\xdc" "\xcf\x31\xf3\x79\xad\xe4\x77\x91\xae\x33\x87\xef\x6e\x53\x53\xc6\x9b" "\x93\xce\x45\x72\xa6\x00\x6f\x61\x78\xc7\xb0\x19\xe2\xf3\x57\xbb\xf6" "\x57\x19\x02\x7a\x8b\xe4\x0a\xbc\xa5\x11\xaa\x3a\xde\xb9\x11\x4d\xe1" "\xb3\x79\x9c\xad\x3b\xe4\xcd\x46\xab\x2c\x10\xb5\x4e\x72\x4d\xb5\xc9" "\xc9\x35\x80\x0f\x2c\x1c\xfd\x32\xbb\x03\x1a\x94\xce\x49\xad\xc5\xd5" "\xa5\x60\x4c\x1c\xd5\x97\xec\xd1\x37\x88\x7f\x06\x09\xa1\x9e\xe6\xc6" "\x9a\xdf\xf1\x16\xcd\x14\x6c\xf8\x02\x4f\xad\x45\x2c\xc2\xc7\x5e\xee" "\x83\x9f\x3f\x41\x62\x21\xd1\xad\xf4\xc3\x14\x4e\x0e\x95\x03\xe3\x98" "\x2e\x6b\xd8\xa3\xa8\xd6\xe1\xd7\x95\x47\xa3\x80\x7a\xf5\xd7\xd7\x6e" "\x81\xf1\x6f\x5a\x87\xc9\x0c\xcd\xe8\x49\xe3\xb3\x39\x99\x11\xda\x38" "\xc1\x9b\xb3\x79\xbb\xba\xc3\xa9\x61\x11\x15\xe6\x60\x3e\xb7\x18\xa1" "\x2a\x82\x2e\x5c\x47\xe2\x19\x4c\x97\xbe\x17\x85\xa6\xb0\x82\x65\x3c" "\x90\x9f\x5b\x3c\x8c\x51\x9c\x5a\x21\x8e\xa0\x4b\x88\x5f\x52\x27\x86" "\x06\x94\xb9\x04\xb6\x11\x40\x9d\x99\xbe\x55\x1a\xc2\x21\x63\xb7\x41" "\x2e\xb4\x6b\xbd\x5f\x7d\x4f\x6c\x2a\x31\x15\x26\xf1\x4e\x9f\x84\x97" "\xe4\xcc\x8d\x22\xae\x39\x9c\xb4\xdd\xbc\xbf\x1a\x8a\x53\x0f\x6d\x02" "\x2d\xc1\x7b\x20\x9d\x30\xb0\xd0\xd1\x89\xe6\x6d\x72\x94\x1e\x26\x6c" "\xa0\x48\xee\xf0\x5a\xe6\xd2\x78\x66\xb1\x98\x67\xf9\xb7\xdd\x11\x40" "\xf9\x7b\x0e\x98\x42\xa6\x22\x59\x24\x65\x2b\x0a\x31\x09\xc7\xe2\x3c" "\x5c\xdf\x97\xcb\x02\x5a\x59\x00\x85\x45\x4f\x7f\x90\x93\x4f\xd9\xab" "\xbe\xa1\x32\x5a\x53\x20\x9c\xfb\xce\xb3\x6f\x4f\xd8\x3e\x68\xeb\x6a" "\x76\x5a\x3a\x43\x8e\x5e\x15\x7d\x97\xf7\x23\x4b\x59\x81\xd2\x90\x36" "\x61\x8b\x5a\x27\x2e\x7c\xc4\x59\x8f\x8f\xab\xde\x62\xdb\x7d\x78\xe1" "\x76\x35\x26\x4c\x8e\x96\x55\xdc\x88\xad\x96\x81\x4a\xe9\x50\xc4\xe0" "\xc6\xe3\xc3\xd0\xaf\xa8\x47\x9e\xe8\x7f\x2d\xce\xa9\xa5\x47\x61\xc6" "\xae\x23\x4f\x1a\x1c\xd0\x0a\xc8\x2e\x18\xaa\xa1\x33\x57\xa2\xd7\xd2" "\xb3\x52\x57\xdd\x7b\x31\xf3\x3d\xe9\x8f\xfd\x8e\xb1\x85\x8a\x92\x39" "\xa2\x1d\x34\xad\xa7\x8c\x19\x1e\xe8\x22\x25\xfb\x12\xfe\x56\xfd\xd8" "\x46\xff\x8e\x72\xaa\x29\xf3\x7b\xe2\x76\x88\x6f\x02\xb0\xda\x3a\xc4" "\x0a\xb8\xae\x0e\xb6\x63\x82\xd8\xdd\xb7\x85\x5d\x08\x1e\x2e\x8a\xd1" "\xf8\x52\xf2\x6e\xe4\x2e\xc0\xbe\x7f\xce\xa2\xac\x11\x13\x75\x7b\x5b" "\x8c\x25\xca\x34\x97\x7f\x3b\x05\xe6\x5a\x0b\x4b\x4f\x7f\x4d\x76\xb9" "\xd0\x99\xd8\xd2\x20\x67\x80\x81\xf6\xbb\x61\x40\x64\x19\x69\xe3\x29" "\xa9\x6a\xaa\xe3\x6f\x32\x72\x89\x3d\x79\xc8\xcd\x3b\x27\x1b\xa0\x40" "\x0a\x37\xd5\xe0\x4b\x58\x6c\x2b\x83\x7c\x8c\xe8\x3b\xa4\xbc\x2f\x6a" "\x84\x65\x5a\xa3\xe4\x0f\x0d\x25\x29\x37\xde\x2b\x4f\xc1\x86\xc9\x86" "\x8f\x36\x33\xe1\x8e\xda\x0f\x0a\x4f\x22\x79\x0b\xe2\xa7\x83\xda\x91" "\x6b\xe6\xbb\xb2\x0a\x3f\x78\xf7\x70\xee\xb2\x1a\xa3\x72\x84\x4d\x1c" "\x1a\x6c\x47\x00\x39\xd8\xb6\xa3\x13\xa0\xdc\x8c\x92\xdc\x77\x2b\xb3" "\xc5\x44\x7c\xd1\x78\x9e\x4b\xa4\x4f\xd6\x63\x5f\x4a\x80\x69\x5f\xf1" "\xfd\xc4\x16\x7f\xd4\xca\x3c\x16\xe8\x96\x45\x02\x73\x0a\xf2\x64\x36" "\x5e\x9b\xf4\x86\xa3\x9c\xd6\x14\x6a\xcd\xff\x71\x3c\x12\x48\xb9\xa4" "\xe7\x1f\x4b\x5a\x2c\x28\x77\x1f\xff\xb1\xee\xec\x12\x51\xc5\xcb\xf5" "\x5b\x73\xcb\x28\x70\xbc\xdb\x28\xb3\xec\x05\xbd\x29\x7e\xd6\xfa\xa6" "\xae\x28\xd7\x23\xb9\x4e\xaa\x6e\x71\xb9\x4d\xf6\xf1\xf3\x1f\x34\xc2" "\x8e\x16\x86\x96\x57\x99\x16\xbb\x71\xee\x92\xbd\x1f\xa3\xd2\xa8\x45" "\x8c\xbb\xfc\x54\x80\xfa\x14\x21\xfc\x36\xe6\x44\xd6\x93\x41\xd2\xc3" "\x3e\xa6\x71\x62\xf2\xae\x05\xe1\xb5\x68\xc0\x48\xdc\xef\xdb\x89\x02" "\x0b\x6c\xf4\xf9\x61\xc1\xb3\x09\xe1\x49\xe3\xe8\x46\xf9\xd3\x6d\x99" "\x3b\xea\x07\x43\xa1\xc4\x4d\x35\xab\xa0\x30\x09\xfc\xef\x92\xd9\xff" "\xbe\x5a\xa3\x00\x12\x61\x7f\x5d\x7a\x22\x01\x24\xcc\x08\x31\xde\xde" "\xa3\x21\x19\x38\x60\xa4\x29\x98\x79\x39\xa4\xe1\x59\x10\x3c\xa7\x66" "\xb6\x40\x07\x04\x6a\x74\x47\x82\x9f\x6d\x49\xe5\xab\x2a\x96\x73\x35" "\x78\x3d\x5f\x22\x63\xa3\xa7\x71\xaf\x4e\x00\xf2\x13\x1f\x81\x1c\x8f" "\xc3\x3d\xc6\x6b\x65\x64\xe2\xe7\xac\xda\x83\x18\xe8\x71\x74\x43\x2d" "\x0e\x1f\x44\x01\x17\xc8\x1e\xdb\x37\x9e\xaf\x0e\x1e\xec\xb3\xc4\xb2" "\x11\x99\xc0\xe4\x32\x43\x19\x15\x54\x50\x81\xb0\x79\xcd\x45\x36\xf3" "\x94\x73\x18\x8b\x7d\xc7\xe7\x2f\x96\x3c\x5d\x35\xd3\xc7\x6d\x6f\xe7" "\x20\xac\x79\xdb\xea\xd8\x07\xda\xfb\x7d\x2a\xcf\x62\x48\x77\x11\x5a" "\x8b\xb0\x50\x53\xd5\x06\x3e\x25\x11\x04\xb0\xe6\x84\x0d\x41\xa7\xa9" "\x4e\xf6\xc7\xc0\xa3\xe7\x1c\x54\x14\xb9\x1b\x14\xa5\x14\x43\x3a\x51" "\x92\x98\xdf\xb4\xaf\x02\x3b\x49\x12\x13\xc5\x64\x71\x72\xfb\xb0\x24" "\x77\x7f\xf8\xe5\xe4\x7d\x89\xc6\xa7\x87\xc9\x20\xe6\xf3\xc7\xee\x7a" "\x4f\x58\xc4\x5a\x84\x17\xa9\x18\xe0\x0c\x66\x98\x8e\xdc\x7d\x4d\x34" "\x2c\xff\xe7\xd6\x6f\xe9\x31\xb5\xb9\xbb\x83\xa7\xf2\xff\xa7\xe1\x24" "\xfc\xbd\xc2\xe5\xfb\x26\x22\x55\x54\xd9\x2b\x02\x01\x4e\xe2\x01\xbe" "\x2e\x7e\x19\x23\xce\xb4\x0d\x90\x71\xef\x9e\x5d\xb0\xf2\xd2\x65\x76" "\x5e\xdf\x26\x00\x92\x6b\xef\x78\x18\xc7\xb0\x5e\xb1\xf2\xe9\x0f\xc7" "\xce\x37\xc1\xfd\xc0\xcc\xb5\xab\x9b\x09\x51\x72\x8f\x15\xd5\x79\xe3" "\x68\xeb\xc7\x9c\x9b\x2c\x71\xe3\x99\xcb\xee\x40\xfd\x4b\xf4\x62\x68" "\xe8\x2f\x69\x49\xe8\xf2\x4d\x1d\x8c\x69\x0a\xed\x9d\x4d\xcb\x18\x28" "\x3c\x1c\x45\x6e\x38\xf5\xf4\x6d\x9d\xbe\x68\x35\x9d\x55\x20\x94\x52" "\x8c\x20\xa4\x0f\x07\xac\x4f\xfc\xbd\xd7\x2b\x13\x1b\x5f\x89\xf7\x41" "\x32\x0d\x6b\x89\x7a\x30\xe1\x8b\xa2\x1a\x89\x7a\x50\x3f\x0f\x6d\xa8" "\xbf\xd7\x4f\x8c\x7c\xc7\x65\x99\xb7\x73\xa8\xdd\x94\xa6\xc4\x49\x8a" "\xf8\xd6\x54\x9f\x2a\x38\x66\x88\xa6\x7a\x64\xa2\xe3\x48\x23\xc1\x7b" "\x74\x8b\x0c\xaf\x57\xe8\xea\x8f\x5e\x07\x1d\x51\x72\x40\x09\xc9\xde" "\xed\x69\xac\x49\x81\xae\x74\x77\x5c\x5b\xcd\x6a\x4c\x91\xbd\x56\xdc" "\x4d\xee\x9f\xf8\x97\xd2\x69\x9b\x17\x6c\x53\xbe\x7b\x59\xbe\xef\x5f" "\x36\x2a\x80\x78\x47\x8a\xd5\xd3\x96\xb7\x06\x0c\x46\xb7\xb3\xa0\x07" "\x82\xd6\x6e\x59\x90\xbd\xe0\x23\xa9\xd9\xf0\x45\x35\x09\x85\x3e\x39" "\xbe\x13\x78\x33\xd3\x8d\xe4\x41\xf9\x27\x82\x71\x8e\xbd\x4b\x37\x81" "\xb8\x42\x9f\x15\x5a\xb4\xf8\xe3\x24\xb2\xc2\x61\x9b\x56\x63\x34\x58" "\x25\x64\xc1\xdc\x68\x52\xb4\xcb\x68\xf3\x50\xb2\x6a\x1d\xe7\xe2\x71" "\x88\x81\x40\xa2\x47\xa3\xb5\xfb\xa4\x6e\x77\xea\xad\x79\x1d\x19\x1a" "\xa8\xb5\x20\x72\x3d\xcc\x35\x6d\xd2\x2b\xa4\xed\xff\x58\xef\xf4\x74" "\xc9\x67\x8d\xe3\x6c\xe9\x16\x1a\x25\xbd\x47\xe9\x91\xbf\x67\x04\x78" "\xcc\x66\xb4\xbe\xa8\xdd\xd7\x4d\x7e\xda\x65\xce\xeb\xdd\x5c\x25\xff" "\xc7\xd4\xa3\x44\x7d\x50\x91\xfa\x27\x54\x4b\x61\x8b\x59\xbe\xac\x5b" "\xe4\xd9\x7e\x1a\xd7\x7a\x22\xf5\xaa\x24\x36\x19\x3e\x8d\x05\x7a\xd3" "\x0d\xa2\xbf\xfc\x67\xff\xe0\x4d\x0b\x2c\xb6\xd5\xec\xb3\xeb\xc5\x60" "\x52\x17\xb1\x8c\x3d\xd9\x47\x85\x75\x59\x3f\x16\xb3\x7d\x09\x08\xf4" "\xbf\x8e\xa1\x61\xff\xd8\x98\x63\x5c\xa3\x3d\x10\xe6\xe6\x59\x94\x47" "\xa5\xd5\x99\x42\x85\xdf\xe4\x47\x3f\xca\xcb\xb4\x8b\xf8\x0a\x99\x40" "\xb5\x54\xc9\x9a\x75\xc1\xa1\xcc\xe3\x8e\x7d\xad\x4a\x2c\xa9\x12\xc5" "\x66\x75\x50\x91\x7c\xf8\x70\x59\xe0\xd8\x5f\xb0\x5b\x3c\x7e\x74\x43" "\xee\x9e\x2a\x82\x13\xab\xd1\x85\x37\xec\x14\x41\xd8\xcd\xe8\x3a\xed" "\x3b\xf9\x5d\x8b\x47\x99\xf2\x55\xb3\xf4\xd7\xa7\xe8\x0e\xb6\x31\x1c" "\xff\x41\x08\x46\x9d\x23\xd5\xde\xd7\xeb\xa1\x3d\xb1\xf3\x1b\xbe\xb8" "\x70\xcf\x7c\xa1\xe9\xcf\xeb\x42\xa7\xe5\x40\x85\xde\x6a\x05\xbe\x52" "\x5a\xba\x37\xfa\x5e\xca\x4a\xa8\xfb\x4c\x50\x9b\xe7\x6a\x3b\x02\x14" "\x41\xca\x0a\x74\x4c\x68\xce\x37\xbc\xb5\x2d\x63\x1b\x7d\x71\x12\xc3" "\x29\xd6\xf8\xfe\xd3\x0a\x47\xc7\x0c\xf8\x23\xbe\x47\x70\xe6\x67\x96" "\xe4\xbb\xdf\xcc\x85\x58\x3b\x88\x40\x67\xe9\x2c\x9d\x22\x9f\x5a\xe5" "\xcb\x7c\x7f\x3e\x4e\xce\xc3\x20\x10\xfc\xce\x2f\xc9\x77\x20\x5b\x47" "\x88\x56\xbc\x18\xe5\xc5\xbb\x20\x40\x9f\x87\x9f\x01\x6e\xf6\x4f\x63" "\xc5\x5b\xc0\x4b\x65\x71\xed\x7e\x9b\xd7\x45\xde\x12\x09\xf8\x59\xfd" "\x56\x47\x84\x4f\x4a\xa5\x0e\xe5\xda\x95\xed\x91\xa3\xd4\x22\x18\x10" "\xa0\x0e\x8a\x5f\x39\x2b\xec\xb4\xc3\xe6\x9b\x7f\x43\xf3\x51\xe2\x0f" "\x78\x86\x60\x3c\x5c\x0f\x5a\x34\x87\x4e\x37\x74\x74\x62\x47\x96\x15" "\x08\x1a\xee\x80\x0d\x1d\x9f\x36\x72\xa8\xd8\x07\xa6\x20\x80\x49\x3c" "\xfe\xcc\xfd\xf6\x0c\xe0\x9a\x54\xa2\x03\x99\xda\x25\xe7\x49\x2d\xcb" "\x2c\xd8\x2e\x89\x8a\x31\xfd\x44\xc6\x41\xb6\xf2\x2f\x41\x7a\x31\xbc" "\x9c\xb0\x71\xb9\xe7\x14\x04\x3e\xe7\x71\x4b\xb4\xf4\xd7\xad\xae\xc8" "\xee\x69\xdd\x20\xb2\xf0\xe2\x51\x38\x96\xdb\x00\x73\xdc\x73\x93\x05" "\x42\x45\xa2\x13\x59\xef\xdc\x31\xfa\x5b\x85\x48\x08\xb5\xd8\x5f\x4e" "\x10\x3a\xdd\xe0\xd4\x4e\x10\x80\xb1\x81\x8a\x89\x59\xfa\xe3\x6e\xd6" "\xa2\x26\x0c\x03\x9b\xce\xd9\x5d\xf4\x07\xed\xae\x1c\x5e\x1c\x87\x6c" "\x77\x21\xba\x1c\xb1\x95\x6c\xe2\x1e\x70\x2c\x7b\xe3\xac\x31\xc2\xd0" "\xe9\x98\x87\x47\xc0\xd6\x0a\xa6\xa6\x27\x4a\x5a\xb5\x1e\x63\x41\xa1" "\x89\x81\x78\x23\xad\xc5\xb9\x70\x99\x2d\x15\xe9\xd8\x7e\x97\x93\x99" "\x14\xbd\xc3\x8f\x44\x8a\xb3\xba\x78\x2f\x94\xfc\x68\x68\xfb\xda\xbb" "\x4d\xdc\x75\xe6\x08\xad\x5b\x7e\x3d\x03\xdb\xbd\xaa\x79\xbd\xb7\x02" "\xda\x2d\x94\x02\x29\xaf\x74\xfa\xc2\x36\xbb\xec\x59\x77\x77\x67\x96" "\x60\x31\x09\xb1\xb3\x85\x8c\x77", 4088); syscall(__NR_ioctl, -1, 0x5000940f, 0x20000400ul); break; case 6: syscall(__NR_ioctl, r[2], 0xae80, 0ul); break; case 7: syscall(__NR_ioctl, r[2], 0xae80, 0ul); break; } } int main(void) { syscall(__NR_mmap, 0x1ffff000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul); syscall(__NR_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x32ul, -1, 0ul); syscall(__NR_mmap, 0x21000000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul); use_temporary_dir(); do_sandbox_none(); return 0; }