Message ID | 20220820070331.48817-1-harshit.m.mogalapalli@oracle.com (mailing list archive) |
---|---|
State | Awaiting Upstream |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | netfilter: ebtables: fix a NULL pointer dereference in ebt_do_table() | expand |
Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com> wrote: > In ebt_do_table() function dereferencing 'private->hook_entry[hook]' > can lead to NULL pointer dereference. So add a check to prevent that. This looks incorrect, i.e. paperimg over the problem. If hook_entry[hook] is NULL, how did this make it to the eval loop? I guess ebtables lacks a sanity check on incoming ruleset?
On 20/08/22 9:56 pm, Florian Westphal wrote: > Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com> wrote: >> In ebt_do_table() function dereferencing 'private->hook_entry[hook]' >> can lead to NULL pointer dereference. So add a check to prevent that. > Hi Florian, Thanks a lot for checking the patch. > This looks incorrect, i.e. paperimg over the problem. > Okay. > If hook_entry[hook] is NULL, how did this make it to the eval loop? > When I run the reproducer and have 'private->hook_entry[hook]' printed, it was NULL, so thought of adding a NULL check to prevent the NULL dereference. Attaching the C reproducer. Regards, Harshit > I guess ebtables lacks a sanity check on incoming ruleset? > {\rtf1\ansi\ansicpg1252\cocoartf2639 \cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fmodern\fcharset0 Courier;} {\colortbl;\red255\green255\blue255;\red0\green0\blue0;} {\*\expandedcolortbl;;\cssrgb\c0\c0\c0;} \paperw11900\paperh16840\margl1440\margr1440\vieww11520\viewh8400\viewkind0 \deftab720 \pard\pardeftab720\partightenfactor0 \f0\fs26 \cf0 \expnd0\expndtw0\kerning0 \outl0\strokewidth0 \strokec2 #define _GNU_SOURCE \ \ #include <arpa/inet.h>\ #include <endian.h>\ #include <errno.h>\ #include <fcntl.h>\ #include <net/if.h>\ #include <net/if_arp.h>\ #include <netinet/in.h>\ #include <pthread.h>\ #include <sched.h>\ #include <stdarg.h>\ #include <stdbool.h>\ #include <stdint.h>\ #include <stdio.h>\ #include <stdlib.h>\ #include <string.h>\ #include <sys/epoll.h>\ #include <sys/ioctl.h>\ #include <sys/mount.h>\ #include <sys/prctl.h>\ #include <sys/resource.h>\ #include <sys/socket.h>\ #include <sys/stat.h>\ #include <sys/syscall.h>\ #include <sys/time.h>\ #include <sys/types.h>\ #include <sys/uio.h>\ #include <sys/wait.h>\ #include <unistd.h>\ \ #include <linux/capability.h>\ #include <linux/genetlink.h>\ #include <linux/if_addr.h>\ #include <linux/if_ether.h>\ #include <linux/if_link.h>\ #include <linux/if_tun.h>\ #include <linux/in6.h>\ #include <linux/ip.h>\ #include <linux/neighbour.h>\ #include <linux/net.h>\ #include <linux/netlink.h>\ #include <linux/rfkill.h>\ #include <linux/rtnetlink.h>\ #include <linux/tcp.h>\ #include <linux/veth.h>\ \ static unsigned long long procid;\ \ 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 struct nlmsg nlmsg;\ \ #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 MAX_FDS 30\ \ #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);\ \}\ \ 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)) \{\ \}\ if (symlink("/dev/binderfs", "./binderfs")) \{\ \}\ \}\ \ 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_netdevices();\ setup_binderfs();\ loop();\ exit(1);\ \}\ \ static void close_fds()\ \{\ for (int fd = 3; fd < MAX_FDS; fd++)\ close(fd);\ \}\ \ static void setup_binfmt_misc()\ \{\ if (mount(0, "/proc/sys/fs/binfmt_misc", "binfmt_misc", 0, 0)) \{\ \}\ write_file("/proc/sys/fs/binfmt_misc/register", ":syz0:M:0:\\x01::./file0:");\ write_file("/proc/sys/fs/binfmt_misc/register", ":syz1:M:1:\\x02::./file0:POC");\ \}\ \ static void setup_sysctl()\ \{\ char mypid[32];\ snprintf(mypid, sizeof(mypid), "%d", getpid());\ struct \{\ const char* name;\ const char* data;\ \} files[] = \{\ \{"/sys/kernel/debug/x86/nmi_longest_ns", "10000000000"\},\ \{"/proc/sys/kernel/hung_task_check_interval_secs", "20"\},\ \{"/proc/sys/net/core/bpf_jit_kallsyms", "1"\},\ \{"/proc/sys/net/core/bpf_jit_harden", "0"\},\ \{"/proc/sys/kernel/kptr_restrict", "0"\},\ \{"/proc/sys/kernel/softlockup_all_cpu_backtrace", "1"\},\ \{"/proc/sys/fs/mount-max", "100"\},\ \{"/proc/sys/vm/oom_dump_tasks", "0"\},\ \{"/proc/sys/debug/exception-trace", "0"\},\ \{"/proc/sys/kernel/printk", "7 4 1 3"\},\ \{"/proc/sys/net/ipv4/ping_group_range", "0 65535"\},\ \{"/proc/sys/kernel/keys/gc_delay", "1"\},\ \{"/proc/sys/vm/oom_kill_allocating_task", "1"\},\ \{"/proc/sys/kernel/ctrl-alt-del", "0"\},\ \{"/proc/sys/kernel/cad_pid", mypid\},\ \};\ for (size_t i = 0; i < sizeof(files) / sizeof(files[0]); i++) \{\ if (!write_file(files[i].name, files[i].data))\ printf("write to %s failed: %s\\n", files[i].name, strerror(errno));\ \}\ \}\ \ uint64_t r[1] = \{0xffffffffffffffff\};\ \ void loop(void)\ \{\ intptr_t res = 0;\ res = syscall(__NR_socket, 2ul, 2ul, 0x73);\ if (res != -1)\ r[0] = res;\ memcpy((void*)0x20000040, "filter\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000", 32);\ *(uint32_t*)0x20000060 = 6;\ *(uint32_t*)0x20000064 = 0;\ *(uint32_t*)0x20000068 = 0x90;\ *(uint64_t*)0x20000070 = 0;\ *(uint64_t*)0x20000078 = 0x20000400;\ *(uint64_t*)0x20000080 = 0x20000430;\ *(uint64_t*)0x20000088 = 0;\ *(uint64_t*)0x20000090 = 0;\ *(uint64_t*)0x20000098 = 0;\ *(uint32_t*)0x200000a0 = 0;\ *(uint64_t*)0x200000a8 = 0;\ *(uint64_t*)0x200000b0 = 0x20000400;\ *(uint32_t*)0x20000400 = 0;\ memset((void*)0x20000404, 0, 32);\ *(uint32_t*)0x20000424 = 0;\ *(uint32_t*)0x20000428 = -1;\ *(uint32_t*)0x2000042c = 0;\ *(uint32_t*)0x20000430 = 0;\ memset((void*)0x20000434, 0, 32);\ *(uint32_t*)0x20000454 = 0;\ *(uint32_t*)0x20000458 = -1;\ *(uint32_t*)0x2000045c = 0;\ *(uint32_t*)0x20000460 = 0;\ memset((void*)0x20000464, 0, 32);\ *(uint32_t*)0x20000484 = 0;\ *(uint32_t*)0x20000488 = 0xfffffffc;\ *(uint32_t*)0x2000048c = 0;\ syscall(__NR_setsockopt, r[0], 0, 0x80, 0x20000040ul, 0x108ul);\ close_fds();\ \}\ 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);\ setup_sysctl();\ setup_binfmt_misc();\ do_sandbox_none();\ return 0;\ \}\ }
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index f2dbefb61ce8..d19d439a66c5 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -217,6 +217,11 @@ unsigned int ebt_do_table(void *priv, struct sk_buff *skb, else cs = NULL; chaininfo = private->hook_entry[hook]; + if (!chaininfo) { + read_unlock_bh(&table->lock); + return NF_DROP; + } + nentries = private->hook_entry[hook]->nentries; point = (struct ebt_entry *)(private->hook_entry[hook]->data); counter_base = cb_base + private->hook_entry[hook]->counter_offset;
In ebt_do_table() function dereferencing 'private->hook_entry[hook]' can lead to NULL pointer dereference. So add a check to prevent that. Kernel panic: [ 119.229105][ T31] general protection fault, probably for non-canonical address 0xdffffc0000000005: 0000 [#1] PREEMPT SMP KASAN [ 119.230280][ T31] KASAN: null-ptr-deref in range [0x0000000000000028-0x000000000000002f] [ 119.231043][ T31] CPU: 3 PID: 31 Comm: kworker/3:0 Not tainted 6.0.0-rc1 #1 [ 119.231652][ T31] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.11.0-2.el7 04/01/2014 [ 119.232440][ T31] Workqueue: mld mld_ifc_work [ 119.232846][ T31] RIP: 0010:ebt_do_table+0x1dc/0x1ce0 [ 119.233291][ T31] Code: 89 fa 48 c1 ea 03 80 3c 02 00 0f 85 5c 16 00 00 48 b8 00 00 00 00 00 fc ff df 49 8b 6c df 08 48 8d 7d 2c 48 89 fa 48 c1 ea 03 <0f> b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 08 84 d2 0f 85 88 [ 119.234920][ T31] RSP: 0018:ffffc90000347178 EFLAGS: 00010217 [ 119.235425][ T31] RAX: dffffc0000000000 RBX: 0000000000000003 RCX: ffffffff8158677b [ 119.236097][ T31] RDX: 0000000000000005 RSI: ffffffff889a7b80 RDI: 000000000000002c [ 119.236764][ T31] RBP: 0000000000000000 R08: 0000000000000001 R09: ffff888101a78443 [ 119.237425][ T31] R10: ffffed102034f088 R11: 000200100040dd86 R12: ffffc90001111018 [ 119.238100][ T31] R13: ffffc90001103080 R14: ffffc90001111000 R15: ffffc90001103000 [ 119.238769][ T31] FS: 0000000000000000(0000) GS:ffff88811a380000(0000) knlGS:0000000000000000 [ 119.239592][ T31] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 119.240221][ T31] CR2: 00007f6a9adda000 CR3: 0000000100be3000 CR4: 00000000000006e0 [ 119.240970][ T31] Call Trace: [ 119.241253][ T31] <TASK> [ 119.241495][ T31] ? ip6_output+0x1f4/0x6e0 [ 119.241877][ T31] ? NF_HOOK.constprop.0+0xe6/0x5f0 [ 119.242309][ T31] ? mld_ifc_work+0x564/0xaa0 [ 119.242708][ T31] ? kthread+0x297/0x340 [ 119.243060][ T31] ? ret_from_fork+0x22/0x30 [ 119.243454][ T31] ? br_multicast_count+0xbf/0x8d0 [ 119.243896][ T31] ? rcu_read_lock_sched_held+0xd/0xa0 [ 119.244356][ T31] ? compat_copy_ebt_replace_from_user+0x380/0x380 [ 119.244907][ T31] ? compat_copy_ebt_replace_from_user+0x380/0x380 [ 119.245454][ T31] nf_hook_slow+0xb1/0x170 [ 119.245835][ T31] __br_forward+0x289/0x730 [ 119.246219][ T31] ? br_forward_finish+0x320/0x320 [ 119.246656][ T31] ? br_dev_queue_push_xmit+0x650/0x650 [ 119.247118][ T31] ? memcpy+0x39/0x60 [ 119.247444][ T31] ? __skb_clone+0x56c/0x750 [ 119.247845][ T31] maybe_deliver+0x24b/0x380 [ 119.248234][ T31] br_flood+0xc6/0x390 [ 119.248577][ T31] br_dev_xmit+0xa2e/0x12c0 [ 119.248975][ T31] ? rcu_read_lock_sched_held+0xd/0xa0 [ 119.249498][ T31] ? br_netpoll_setup+0x170/0x170 [ 119.249987][ T31] ? fib_rules_lookup+0x2eb/0x9d0 [ 119.250462][ T31] ? lock_repin_lock+0x30/0x420 [ 119.250922][ T31] ? rcu_read_lock_sched_held+0xd/0xa0 [ 119.251376][ T31] ? lock_acquire+0x510/0x630 [ 119.251773][ T31] ? netif_inherit_tso_max+0x1e0/0x1e0 [ 119.252228][ T31] dev_hard_start_xmit+0x151/0x660 [ 119.252663][ T31] __dev_queue_xmit+0x240e/0x3200 [ 119.253080][ T31] ? ip6mr_rtm_dumproute+0x530/0x530 [ 119.253522][ T31] ? netdev_core_pick_tx+0x2a0/0x2a0 [ 119.253968][ T31] ? unwind_next_frame+0x3de/0x1c90 [ 119.254403][ T31] ? rcu_read_lock_sched_held+0xd/0xa0 [ 119.254872][ T31] ? lock_acquire+0x510/0x630 [ 119.255266][ T31] ? rcu_read_lock_sched_held+0xd/0xa0 [ 119.255724][ T31] ? lock_release+0x5a2/0x840 [ 119.256119][ T31] ? mroute6_is_socket+0x14d/0x220 [ 119.256549][ T31] ? rcu_read_lock_sched_held+0xd/0xa0 [ 119.257064][ T31] ? lock_acquire+0x510/0x630 [ 119.257507][ T31] ? rcu_read_lock_sched_held+0xd/0xa0 [ 119.258016][ T31] ? lock_release+0x5a2/0x840 [ 119.258410][ T31] ? lock_release+0x840/0x840 [ 119.258812][ T31] ? ip6_finish_output+0x779/0x1190 [ 119.259304][ T31] ? lock_downgrade+0x7b0/0x7b0 [ 119.259778][ T31] ? rcu_read_lock_bh_held+0xd/0x90 [ 119.260275][ T31] ? ___neigh_lookup_noref.constprop.0+0x266/0x6d0 [ 119.260896][ T31] ? ip6_finish_output2+0x861/0x1690 [ 119.261343][ T31] ip6_finish_output2+0x861/0x1690 [ 119.261776][ T31] ? lock_release+0x5a2/0x840 [ 119.262176][ T31] ? __kasan_kmalloc+0x7f/0xa0 [ 119.262574][ T31] ? ip6_mtu+0x139/0x320 [ 119.262942][ T31] ? ip6_frag_next+0xcc0/0xcc0 [ 119.263341][ T31] ? rcu_read_lock_sched_held+0xd/0xa0 [ 119.263816][ T31] ? nf_ct_netns_get+0xe0/0xe0 [ 119.264214][ T31] ? rcu_read_lock_sched_held+0xd/0xa0 [ 119.264679][ T31] ? lock_release+0x5a2/0x840 [ 119.265066][ T31] ? nf_conntrack_in.cold+0x9b/0xe2 [ 119.265504][ T31] ? ip6_output+0x4c9/0x6e0 [ 119.265891][ T31] ip6_finish_output+0x779/0x1190 [ 119.266315][ T31] ? nf_hook_slow+0xb1/0x170 [ 119.266711][ T31] ip6_output+0x1f4/0x6e0 [ 119.267069][ T31] ? rcu_read_lock_sched_held+0xd/0xa0 [ 119.267520][ T31] ? ip6_finish_output+0x1190/0x1190 [ 119.267969][ T31] ? NF_HOOK.constprop.0+0x1b3/0x5f0 [ 119.268415][ T31] ? lock_pin_lock+0x184/0x380 [ 119.268817][ T31] ? ip6_fragment+0x2910/0x2910 [ 119.269269][ T31] ? nf_ct_netns_do_get+0x6c0/0x6c0 [ 119.269773][ T31] ? nf_hook_slow+0xb1/0x170 [ 119.270211][ T31] NF_HOOK.constprop.0+0xe6/0x5f0 [ 119.270697][ T31] ? igmp6_mcf_seq_next+0x460/0x460 [ 119.271159][ T31] ? igmp6_mcf_seq_stop+0x130/0x130 [ 119.271600][ T31] ? icmp6_dst_alloc+0x3dc/0x610 [ 119.272030][ T31] mld_sendpack+0x619/0xb50 [ 119.272413][ T31] ? NF_HOOK.constprop.0+0x5f0/0x5f0 [ 119.272867][ T31] ? lock_release+0x840/0x840 [ 119.273254][ T31] mld_ifc_work+0x564/0xaa0 [ 119.273642][ T31] ? pwq_activate_inactive_work+0xb2/0x190 [ 119.274126][ T31] process_one_work+0x875/0x1440 [ 119.274543][ T31] ? lock_release+0x840/0x840 [ 119.274936][ T31] ? pwq_dec_nr_in_flight+0x230/0x230 [ 119.275381][ T31] ? rwlock_bug.part.0+0x90/0x90 [ 119.275801][ T31] worker_thread+0x598/0xec0 [ 119.276187][ T31] ? process_one_work+0x1440/0x1440 [ 119.276613][ T31] kthread+0x297/0x340 [ 119.276958][ T31] ? kthread_complete_and_exit+0x20/0x20 [ 119.277422][ T31] ret_from_fork+0x22/0x30 [ 119.277796][ T31] </TASK> [ 119.278048][ T31] Modules linked in: [ 119.278377][ T31] Dumping ftrace buffer: [ 119.278733][ T31] (ftrace buffer empty) [ 119.279151][ T31] ---[ end trace 0000000000000000 ]--- [ 119.279679][ T31] RIP: 0010:ebt_do_table+0x1dc/0x1ce0 [ 119.280187][ T31] Code: 89 fa 48 c1 ea 03 80 3c 02 00 0f 85 5c 16 00 00 48 b8 00 00 00 00 00 fc ff df 49 8b 6c df 08 48 8d 7d 2c 48 89 fa 48 c1 ea 03 <0f> b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 08 84 d2 0f 85 88 [ 119.282006][ T31] RSP: 0018:ffffc90000347178 EFLAGS: 00010217 [ 119.282569][ T31] RAX: dffffc0000000000 RBX: 0000000000000003 RCX: ffffffff8158677b [ 119.283308][ T31] RDX: 0000000000000005 RSI: ffffffff889a7b80 RDI: 000000000000002c [ 119.284056][ T31] RBP: 0000000000000000 R08: 0000000000000001 R09: ffff888101a78443 [ 119.284811][ T31] R10: ffffed102034f088 R11: 000200100040dd86 R12: ffffc90001111018 [ 119.285549][ T31] R13: ffffc90001103080 R14: ffffc90001111000 R15: ffffc90001103000 [ 119.286284][ T31] FS: 0000000000000000(0000) GS:ffff88811a380000(0000) knlGS:0000000000000000 [ 119.287119][ T31] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 119.287741][ T31] CR2: 00007f6a9adda000 CR3: 0000000100be3000 CR4: 00000000000006e0 [ 119.288489][ T31] Kernel panic - not syncing: Fatal exception in interrupt [ 119.298556][ T31] Dumping ftrace buffer: [ 119.298974][ T31] (ftrace buffer empty) [ 119.299399][ T31] Kernel Offset: disabled [ 119.299823][ T31] Rebooting in 86400 seconds.. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Reported-by: syzkaller <syzkaller@googlegroups.com> Signed-off-by: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com> --- Testing is only done with reproducer. net/bridge/netfilter/ebtables.c | 5 +++++ 1 file changed, 5 insertions(+)