Index | Thread | Search

From:
Marc Jorge <openbsd@cypher-fox.com>
Subject:
Re: relayd: accept icmp packets with IP options
To:
tech@openbsd.org
Date:
Wed, 2 Sep 2026 20:01:18 +0200

Download raw body.

Thread
On 8/13/26 5:50 PM, Marc Jorge wrote:
> 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));

ping