Module Name: src Committed By: maxv Date: Tue Feb 6 15:48:02 UTC 2018
Modified Files: src/sys/netinet: ip_reass.c Log Message: Add one more check in ip_reass_packet(): make sure that the end of each fragment does not exceed IP_MAXPACKET. In ip_reass(), we only check the final length of the reassembled packet against IP_MAXPACKET. But there is an integer overflow that can happen a little earlier. We are doing: i = ntohs(p->ipqe_ip->ip_off) + ntohs(p->ipqe_ip->ip_len) - ntohs(ip->ip_off); [...] ip->ip_off = htons(ntohs(ip->ip_off) + i); It is possible that ntohs(p->ipqe_ip->ip_off) + ntohs(p->ipqe_ip->ip_len) > 65535 so the computation of ip_off wraps to zero. This breaks an assumption in the reassembler - it expects the list of fragments to be ordered by offset, and here it's not ordered anymore. (Un)Fortunately I couldn't turn this into anything exploitable. With the new check, it is guaranteed that ip_off+ip_len<=65535. To generate a diff of this commit: cvs rdiff -u -r1.11 -r1.12 src/sys/netinet/ip_reass.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/netinet/ip_reass.c diff -u src/sys/netinet/ip_reass.c:1.11 src/sys/netinet/ip_reass.c:1.12 --- src/sys/netinet/ip_reass.c:1.11 Wed Jan 11 13:08:29 2017 +++ src/sys/netinet/ip_reass.c Tue Feb 6 15:48:02 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: ip_reass.c,v 1.11 2017/01/11 13:08:29 ozaki-r Exp $ */ +/* $NetBSD: ip_reass.c,v 1.12 2018/02/06 15:48:02 maxv Exp $ */ /* * Copyright (c) 1982, 1986, 1988, 1993 @@ -46,7 +46,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ip_reass.c,v 1.11 2017/01/11 13:08:29 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ip_reass.c,v 1.12 2018/02/06 15:48:02 maxv Exp $"); #include <sys/param.h> #include <sys/types.h> @@ -629,6 +629,11 @@ ip_reass_packet(struct mbuf **m0, struct return EINVAL; } + if (off + len > IP_MAXPACKET) { + IP_STATINC(IP_STAT_BADFRAGS); + return EINVAL; + } + /* * Fragment length and MF flag. Make sure that fragments have * a data length which is non-zero and multiple of 8 bytes.