From: Marc Jorge Subject: relayd: accept icmp packets with IP options To: tech@openbsd.org Date: Thu, 13 Aug 2026 17:50:01 +0200 Hello, We're currently assuming a fixed 20-byte IP header in recv_icmp, which breaks if a packet drops in with IP options. Index: usr.sbin/relayd/check_icmp.c =================================================================== RCS file: /cvs/src/usr.sbin/relayd/check_icmp.c,v diff -u -p -u -r1.50 check_icmp.c --- usr.sbin/relayd/check_icmp.c 15 Jun 2026 11:02:13 -0000 1.50 +++ usr.sbin/relayd/check_icmp.c 13 Aug 2026 15:38:54 -0000 @@ -286,11 +286,13 @@ void recv_icmp(int s, short event, void *arg) { struct ctl_icmp_event *cie = arg; - u_char packet[ICMP_BUF_SIZE]; + u_char packet[ICMP_BUF_SIZE + 40]; /* 40 bytes for reserved IP options */ socklen_t slen; struct sockaddr_storage ss; + struct ip *ip; struct icmp *icp; struct icmp6_hdr *icp6; + u_int hlen; u_int16_t icpid; struct host *host; ssize_t r; @@ -307,17 +309,25 @@ recv_icmp(int s, short event, void *arg) r = recvfrom(s, packet, sizeof(packet), 0, (struct sockaddr *)&ss, &slen); - if (r == -1 || r != ICMP_BUF_SIZE) { - if (r == -1 && errno != EAGAIN && errno != EINTR) + if (r == -1) { + if (errno != EAGAIN && errno != EINTR) log_debug("%s: receive error", __func__); goto retry; } if (cie->af == AF_INET) { - icp = (struct icmp *)(packet + sizeof(struct ip)); + if (r < (ssize_t)sizeof(*ip)) + goto retry; + ip = (struct ip *)packet; + hlen = ip->ip_hl << 2; + if (hlen < sizeof(*ip) || r < (ssize_t)(hlen + sizeof(*icp))) + goto retry; + icp = (struct icmp *)(packet + hlen); icpid = ntohs(icp->icmp_id); id = icp->icmp_mask; } else { + if (r < (ssize_t)(sizeof(*icp6) + sizeof(id))) + goto retry; icp6 = (struct icmp6_hdr *)packet; icpid = ntohs(icp6->icmp6_id); memcpy(&id, packet + sizeof(*icp6), sizeof(id));