Fri Oct 3 09:21:02 2008 UTC ()
Pull up revision 1.150 (requested by adrianp in ticket #1966).

Fix for CVE-2008-3530 from matt@
Implement improved checking for MTU values on ICMP 'Packet Too Big Messages'


(jdc)
diff -r1.108 -r1.108.8.1 src/sys/netinet6/icmp6.c

cvs diff -r1.108 -r1.108.8.1 src/sys/netinet6/icmp6.c (expand / switch to unified diff)

--- src/sys/netinet6/icmp6.c 2005/01/17 10:16:07 1.108
+++ src/sys/netinet6/icmp6.c 2008/10/03 09:21:02 1.108.8.1
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: icmp6.c,v 1.108 2005/01/17 10:16:07 itojun Exp $ */ 1/* $NetBSD: icmp6.c,v 1.108.8.1 2008/10/03 09:21:02 jdc Exp $ */
2/* $KAME: icmp6.c,v 1.217 2001/06/20 15:03:29 jinmei Exp $ */ 2/* $KAME: icmp6.c,v 1.217 2001/06/20 15:03:29 jinmei Exp $ */
3 3
4/* 4/*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
@@ -52,27 +52,27 @@ @@ -52,27 +52,27 @@
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE. 59 * SUCH DAMAGE.
60 * 60 *
61 * @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94 61 * @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94
62 */ 62 */
63 63
64#include <sys/cdefs.h> 64#include <sys/cdefs.h>
65__KERNEL_RCSID(0, "$NetBSD: icmp6.c,v 1.108 2005/01/17 10:16:07 itojun Exp $"); 65__KERNEL_RCSID(0, "$NetBSD: icmp6.c,v 1.108.8.1 2008/10/03 09:21:02 jdc Exp $");
66 66
67#include "opt_inet.h" 67#include "opt_inet.h"
68#include "opt_ipsec.h" 68#include "opt_ipsec.h"
69 69
70#include <sys/param.h> 70#include <sys/param.h>
71#include <sys/systm.h> 71#include <sys/systm.h>
72#include <sys/malloc.h> 72#include <sys/malloc.h>
73#include <sys/mbuf.h> 73#include <sys/mbuf.h>
74#include <sys/protosw.h> 74#include <sys/protosw.h>
75#include <sys/socket.h> 75#include <sys/socket.h>
76#include <sys/socketvar.h> 76#include <sys/socketvar.h>
77#include <sys/time.h> 77#include <sys/time.h>
78#include <sys/kernel.h> 78#include <sys/kernel.h>
@@ -505,26 +505,29 @@ icmp6_input(mp, offp, proto) @@ -505,26 +505,29 @@ icmp6_input(mp, offp, proto)
505 break; 505 break;
506#endif 506#endif
507 case ICMP6_DST_UNREACH_NOPORT: 507 case ICMP6_DST_UNREACH_NOPORT:
508 code = PRC_UNREACH_PORT; 508 code = PRC_UNREACH_PORT;
509 break; 509 break;
510 default: 510 default:
511 goto badcode; 511 goto badcode;
512 } 512 }
513 goto deliver; 513 goto deliver;
514 514
515 case ICMP6_PACKET_TOO_BIG: 515 case ICMP6_PACKET_TOO_BIG:
516 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_pkttoobig); 516 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_pkttoobig);
517 517
 518 /*
 519 * MTU is checked in icmp6_mtudisc.
 520 */
518 code = PRC_MSGSIZE; 521 code = PRC_MSGSIZE;
519 522
520 /* 523 /*
521 * Updating the path MTU will be done after examining 524 * Updating the path MTU will be done after examining
522 * intermediate extension headers. 525 * intermediate extension headers.
523 */ 526 */
524 goto deliver; 527 goto deliver;
525 528
526 case ICMP6_TIME_EXCEEDED: 529 case ICMP6_TIME_EXCEEDED:
527 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_timeexceed); 530 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_timeexceed);
528 switch (code) { 531 switch (code) {
529 case ICMP6_TIME_EXCEED_TRANSIT: 532 case ICMP6_TIME_EXCEED_TRANSIT:
530 code = PRC_TIMXCEED_INTRANS; 533 code = PRC_TIMXCEED_INTRANS;
@@ -1098,26 +1101,40 @@ icmp6_mtudisc_update(ip6cp, validated) @@ -1098,26 +1101,40 @@ icmp6_mtudisc_update(ip6cp, validated)
1098 struct ip6ctlparam *ip6cp; 1101 struct ip6ctlparam *ip6cp;
1099 int validated; 1102 int validated;
1100{ 1103{
1101 unsigned long rtcount; 1104 unsigned long rtcount;
1102 struct icmp6_mtudisc_callback *mc; 1105 struct icmp6_mtudisc_callback *mc;
1103 struct in6_addr *dst = ip6cp->ip6c_finaldst; 1106 struct in6_addr *dst = ip6cp->ip6c_finaldst;
1104 struct icmp6_hdr *icmp6 = ip6cp->ip6c_icmp6; 1107 struct icmp6_hdr *icmp6 = ip6cp->ip6c_icmp6;
1105 struct mbuf *m = ip6cp->ip6c_m; /* will be necessary for scope issue */ 1108 struct mbuf *m = ip6cp->ip6c_m; /* will be necessary for scope issue */
1106 u_int mtu = ntohl(icmp6->icmp6_mtu); 1109 u_int mtu = ntohl(icmp6->icmp6_mtu);
1107 struct rtentry *rt = NULL; 1110 struct rtentry *rt = NULL;
1108 struct sockaddr_in6 sin6; 1111 struct sockaddr_in6 sin6;
1109 1112
1110 /* 1113 /*
 1114 * The MTU should not be less than the minimal IPv6 MTU except for the
 1115 * hack in ip6_output/ip6_setpmtu where we always include a frag header.
 1116 * In that one case, the MTU might be less than 1280.
 1117 */
 1118 if (__predict_false(mtu < IPV6_MMTU - sizeof(struct ip6_frag))) {
 1119 /* is the mtu even sane? */
 1120 if (mtu < sizeof(struct ip6_hdr) + sizeof(struct ip6_frag) + 8)
 1121 return;
 1122 if (!validated)
 1123 return;
 1124 mtu = IPV6_MMTU - sizeof(struct ip6_frag);
 1125 }
 1126
 1127 /*
1111 * allow non-validated cases if memory is plenty, to make traffic 1128 * allow non-validated cases if memory is plenty, to make traffic
1112 * from non-connected pcb happy. 1129 * from non-connected pcb happy.
1113 */ 1130 */
1114 rtcount = rt_timer_count(icmp6_mtudisc_timeout_q); 1131 rtcount = rt_timer_count(icmp6_mtudisc_timeout_q);
1115 if (validated) { 1132 if (validated) {
1116 if (0 <= icmp6_mtudisc_hiwat && rtcount > icmp6_mtudisc_hiwat) 1133 if (0 <= icmp6_mtudisc_hiwat && rtcount > icmp6_mtudisc_hiwat)
1117 return; 1134 return;
1118 else if (0 <= icmp6_mtudisc_lowat && 1135 else if (0 <= icmp6_mtudisc_lowat &&
1119 rtcount > icmp6_mtudisc_lowat) { 1136 rtcount > icmp6_mtudisc_lowat) {
1120 /* 1137 /*
1121 * XXX nuke a victim, install the new one. 1138 * XXX nuke a victim, install the new one.
1122 */ 1139 */
1123 } 1140 }