Additional length check for IPv6 reassembled fragments.
authorbluhm <bluhm@openbsd.org>
Tue, 26 Mar 2024 23:48:49 +0000 (23:48 +0000)
committerbluhm <bluhm@openbsd.org>
Tue, 26 Mar 2024 23:48:49 +0000 (23:48 +0000)
FreeBSD-SA-23:06.ipv6 security advisory has added an additional
overflow check in frag6_input().  OpenBSD is not affected by that
as the bug was introduced by another change in 2019.  The existing
code is complicated and NetBSD has taken the FreeBSD fix, although
they were also not affected.

The additional check makes the complicated code more robust.  Length
calculation taken from NetBSD.  Discussed with FreeBSD.

OK sashan@ mvs@

sys/netinet6/frag6.c

index 5ecb11f..1b528b3 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: frag6.c,v 1.87 2022/02/22 01:15:02 guenther Exp $     */
+/*     $OpenBSD: frag6.c,v 1.88 2024/03/26 23:48:49 bluhm Exp $        */
 /*     $KAME: frag6.c,v 1.40 2002/05/27 21:40:31 itojun Exp $  */
 
 /*
@@ -404,8 +404,17 @@ frag6_input(struct mbuf **mp, int *offp, int proto, int af)
        /* adjust offset to point where the original next header starts */
        offset = ip6af->ip6af_offset - sizeof(struct ip6_frag);
        pool_put(&ip6af_pool, ip6af);
+       next += offset - sizeof(struct ip6_hdr);
+       if ((u_int)next > IPV6_MAXPACKET) {
+               TAILQ_REMOVE(&frag6_queue, q6, ip6q_queue);
+               frag6_nfrags -= q6->ip6q_nfrag;
+               frag6_nfragpackets--;
+               mtx_leave(&frag6_mutex);
+               pool_put(&ip6q_pool, q6);
+               goto dropfrag;
+       }
        ip6 = mtod(m, struct ip6_hdr *);
-       ip6->ip6_plen = htons((u_short)next + offset - sizeof(struct ip6_hdr));
+       ip6->ip6_plen = htons(next);
        ip6->ip6_src = q6->ip6q_src;
        ip6->ip6_dst = q6->ip6q_dst;
        if (q6->ip6q_ecn == IPTOS_ECN_CE)