Fri Oct 3 09:04:30 2008 UTC ()
Pull up revision 1.150 (requested by adrianp in ticket #1209).

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


(jdc)
diff -r1.123.2.2 -r1.123.2.3 src/sys/netinet6/icmp6.c

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

--- src/sys/netinet6/icmp6.c 2007/05/24 19:13:14 1.123.2.2
+++ src/sys/netinet6/icmp6.c 2008/10/03 09:04:30 1.123.2.3
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: icmp6.c,v 1.123.2.2 2007/05/24 19:13:14 pavel Exp $ */ 1/* $NetBSD: icmp6.c,v 1.123.2.3 2008/10/03 09:04:30 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.123.2.2 2007/05/24 19:13:14 pavel Exp $"); 65__KERNEL_RCSID(0, "$NetBSD: icmp6.c,v 1.123.2.3 2008/10/03 09:04:30 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>
@@ -542,26 +542,29 @@ icmp6_input(struct mbuf **mp, int *offp, @@ -542,26 +542,29 @@ icmp6_input(struct mbuf **mp, int *offp,
542 break; 542 break;
543#endif 543#endif
544 case ICMP6_DST_UNREACH_NOPORT: 544 case ICMP6_DST_UNREACH_NOPORT:
545 code = PRC_UNREACH_PORT; 545 code = PRC_UNREACH_PORT;
546 break; 546 break;
547 default: 547 default:
548 goto badcode; 548 goto badcode;
549 } 549 }
550 goto deliver; 550 goto deliver;
551 551
552 case ICMP6_PACKET_TOO_BIG: 552 case ICMP6_PACKET_TOO_BIG:
553 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_pkttoobig); 553 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_pkttoobig);
554 554
 555 /*
 556 * MTU is checked in icmp6_mtudisc.
 557 */
555 code = PRC_MSGSIZE; 558 code = PRC_MSGSIZE;
556 559
557 /* 560 /*
558 * Updating the path MTU will be done after examining 561 * Updating the path MTU will be done after examining
559 * intermediate extension headers. 562 * intermediate extension headers.
560 */ 563 */
561 goto deliver; 564 goto deliver;
562 565
563 case ICMP6_TIME_EXCEEDED: 566 case ICMP6_TIME_EXCEEDED:
564 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_timeexceed); 567 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_timeexceed);
565 switch (code) { 568 switch (code) {
566 case ICMP6_TIME_EXCEED_TRANSIT: 569 case ICMP6_TIME_EXCEED_TRANSIT:
567 code = PRC_TIMXCEED_INTRANS; 570 code = PRC_TIMXCEED_INTRANS;
@@ -1074,26 +1077,40 @@ icmp6_mtudisc_update(ip6cp, validated) @@ -1074,26 +1077,40 @@ icmp6_mtudisc_update(ip6cp, validated)
1074 struct ip6ctlparam *ip6cp; 1077 struct ip6ctlparam *ip6cp;
1075 int validated; 1078 int validated;
1076{ 1079{
1077 unsigned long rtcount; 1080 unsigned long rtcount;
1078 struct icmp6_mtudisc_callback *mc; 1081 struct icmp6_mtudisc_callback *mc;
1079 struct in6_addr *dst = ip6cp->ip6c_finaldst; 1082 struct in6_addr *dst = ip6cp->ip6c_finaldst;
1080 struct icmp6_hdr *icmp6 = ip6cp->ip6c_icmp6; 1083 struct icmp6_hdr *icmp6 = ip6cp->ip6c_icmp6;
1081 struct mbuf *m = ip6cp->ip6c_m; /* will be necessary for scope issue */ 1084 struct mbuf *m = ip6cp->ip6c_m; /* will be necessary for scope issue */
1082 u_int mtu = ntohl(icmp6->icmp6_mtu); 1085 u_int mtu = ntohl(icmp6->icmp6_mtu);
1083 struct rtentry *rt = NULL; 1086 struct rtentry *rt = NULL;
1084 struct sockaddr_in6 sin6; 1087 struct sockaddr_in6 sin6;
1085 1088
1086 /* 1089 /*
 1090 * The MTU should not be less than the minimal IPv6 MTU except for the
 1091 * hack in ip6_output/ip6_setpmtu where we always include a frag header.
 1092 * In that one case, the MTU might be less than 1280.
 1093 */
 1094 if (__predict_false(mtu < IPV6_MMTU - sizeof(struct ip6_frag))) {
 1095 /* is the mtu even sane? */
 1096 if (mtu < sizeof(struct ip6_hdr) + sizeof(struct ip6_frag) + 8)
 1097 return;
 1098 if (!validated)
 1099 return;
 1100 mtu = IPV6_MMTU - sizeof(struct ip6_frag);
 1101 }
 1102
 1103 /*
1087 * allow non-validated cases if memory is plenty, to make traffic 1104 * allow non-validated cases if memory is plenty, to make traffic
1088 * from non-connected pcb happy. 1105 * from non-connected pcb happy.
1089 */ 1106 */
1090 rtcount = rt_timer_count(icmp6_mtudisc_timeout_q); 1107 rtcount = rt_timer_count(icmp6_mtudisc_timeout_q);
1091 if (validated) { 1108 if (validated) {
1092 if (0 <= icmp6_mtudisc_hiwat && rtcount > icmp6_mtudisc_hiwat) 1109 if (0 <= icmp6_mtudisc_hiwat && rtcount > icmp6_mtudisc_hiwat)
1093 return; 1110 return;
1094 else if (0 <= icmp6_mtudisc_lowat && 1111 else if (0 <= icmp6_mtudisc_lowat &&
1095 rtcount > icmp6_mtudisc_lowat) { 1112 rtcount > icmp6_mtudisc_lowat) {
1096 /* 1113 /*
1097 * XXX nuke a victim, install the new one. 1114 * XXX nuke a victim, install the new one.
1098 */ 1115 */
1099 } 1116 }