DF-3378 / trigger_mrt6_init.c
/* * DF-3378 PoC: MRT6_INIT argument-length gate uses sizeof(int *) (8 on * amd64) instead of sizeof(int) (4) at sys/netinet6/ip6_mroute.c:426. * * A routing daemon calling the standard KAME API * int v = 1; setsockopt(s, IPPROTO_IPV6, MRT6_INIT, &v, sizeof(v)); * gets ENOPROTOOPT on 64-bit DragonFly -- the entire IPv6 multicast * routing subsystem cannot be enabled by any conforming daemon. * * Must run as root (raw ICMPv6 socket requires privilege). * * Expected (stock kernel): * MRT6_INIT(4-byte int arg): rc=-1 errno=42 (Protocol not available) * MRT6_INIT(8-byte arg): rc=0 errno=0 (Success) * * Expected (fixed kernel, m_len >= sizeof(int)): * both rc=0 */ #include <sys/types.h> #include <sys/param.h> /* NBBY for ip6_mroute.h */ #include <sys/socket.h> #include <sys/time.h> #include <netinet/in.h> #include <netinet6/ip6_mroute.h> #include <arpa/inet.h> #include <stdio.h> #include <string.h> #include <errno.h> #include <unistd.h> int main(void) { int s, rc, rc2; int v = 1; long long w = 1; setvbuf(stdout, NULL, _IONBF, 0); s = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); if (s < 0) { printf("socket(AF_INET6,SOCK_RAW,IPPROTO_ICMPV6): %s\n", strerror(errno)); return (1); } errno = 0; rc = setsockopt(s, IPPROTO_IPV6, MRT6_INIT, &v, sizeof(v)); printf("MRT6_INIT(4-byte int arg): rc=%d errno=%d (%s)\n", rc, errno, strerror(errno)); errno = 0; rc2 = setsockopt(s, IPPROTO_IPV6, MRT6_INIT, &w, sizeof(w)); printf("MRT6_INIT(8-byte arg): rc=%d errno=%d (%s)\n", rc2, errno, strerror(errno)); /* * Baseline stock kernel: rc=-1/errno=42 (the bug) and rc2=0 * (8 bytes satisfies the wrong check). Fixed kernel: rc=0. */ return (0); } |