Thu Jun 7 05:03:26 2018 UTC ()
Pull up following revision(s) (requested by maxv in ticket #1607):

        sys/netinet/udp_usrreq.c: revision 1.237 (via patch)

Fix three pretty bad mistakes in NAT-T:

 * If we got a keepalive packet, we need to call m_freem, not m_free.
   Here the next mbufs in the chain are not freed. Seems easy to remotely
   DoS the system by sending fragmented keepalives in a loop.

 * If !ipsec_used, free the mbuf.

 * In udp_input, we need to update 'uh', because udp4_realinput may have
   modified the chain. Perhaps we also need to re-enforce alignment, so
   add an XXX.


(martin)
diff -r1.217 -r1.217.6.1 src/sys/netinet/udp_usrreq.c

cvs diff -r1.217 -r1.217.6.1 src/sys/netinet/udp_usrreq.c (expand / switch to unified diff)

--- src/sys/netinet/udp_usrreq.c 2014/08/09 05:33:01 1.217
+++ src/sys/netinet/udp_usrreq.c 2018/06/07 05:03:26 1.217.6.1
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: udp_usrreq.c,v 1.217 2014/08/09 05:33:01 rtr Exp $ */ 1/* $NetBSD: udp_usrreq.c,v 1.217.6.1 2018/06/07 05:03:26 martin Exp $ */
2 2
3/* 3/*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -56,27 +56,27 @@ @@ -56,27 +56,27 @@
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE. 58 * SUCH DAMAGE.
59 * 59 *
60 * @(#)udp_usrreq.c 8.6 (Berkeley) 5/23/95 60 * @(#)udp_usrreq.c 8.6 (Berkeley) 5/23/95
61 */ 61 */
62 62
63/* 63/*
64 * UDP protocol implementation. 64 * UDP protocol implementation.
65 * Per RFC 768, August, 1980. 65 * Per RFC 768, August, 1980.
66 */ 66 */
67 67
68#include <sys/cdefs.h> 68#include <sys/cdefs.h>
69__KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c,v 1.217 2014/08/09 05:33:01 rtr Exp $"); 69__KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c,v 1.217.6.1 2018/06/07 05:03:26 martin Exp $");
70 70
71#include "opt_inet.h" 71#include "opt_inet.h"
72#include "opt_compat_netbsd.h" 72#include "opt_compat_netbsd.h"
73#include "opt_ipsec.h" 73#include "opt_ipsec.h"
74#include "opt_inet_csum.h" 74#include "opt_inet_csum.h"
75#include "opt_ipkdb.h" 75#include "opt_ipkdb.h"
76#include "opt_mbuftrace.h" 76#include "opt_mbuftrace.h"
77 77
78#include <sys/param.h> 78#include <sys/param.h>
79#include <sys/mbuf.h> 79#include <sys/mbuf.h>
80#include <sys/once.h> 80#include <sys/once.h>
81#include <sys/protosw.h> 81#include <sys/protosw.h>
82#include <sys/socket.h> 82#include <sys/socket.h>
@@ -385,27 +385,35 @@ udp_input(struct mbuf *m, ...) @@ -385,27 +385,35 @@ udp_input(struct mbuf *m, ...)
385 sockaddr_in_init(&dst, &ip->ip_dst, uh->uh_dport); 385 sockaddr_in_init(&dst, &ip->ip_dst, uh->uh_dport);
386 386
387 if ((n = udp4_realinput(&src, &dst, &m, iphlen)) == -1) { 387 if ((n = udp4_realinput(&src, &dst, &m, iphlen)) == -1) {
388 UDP_STATINC(UDP_STAT_HDROPS); 388 UDP_STATINC(UDP_STAT_HDROPS);
389 return; 389 return;
390 } 390 }
391 if (m == NULL) { 391 if (m == NULL) {
392 /* 392 /*
393 * packet has been processed by ESP stuff - 393 * packet has been processed by ESP stuff -
394 * e.g. dropped NAT-T-keep-alive-packet ... 394 * e.g. dropped NAT-T-keep-alive-packet ...
395 */ 395 */
396 return; 396 return;
397 } 397 }
 398
398 ip = mtod(m, struct ip *); 399 ip = mtod(m, struct ip *);
 400 IP6_EXTHDR_GET(uh, struct udphdr *, m, iphlen, sizeof(struct udphdr));
 401 if (uh == NULL) {
 402 UDP_STATINC(UDP_STAT_HDROPS);
 403 return;
 404 }
 405 /* XXX Re-enforce alignment? */
 406
399#ifdef INET6 407#ifdef INET6
400 if (IN_MULTICAST(ip->ip_dst.s_addr) || n == 0) { 408 if (IN_MULTICAST(ip->ip_dst.s_addr) || n == 0) {
401 struct sockaddr_in6 src6, dst6; 409 struct sockaddr_in6 src6, dst6;
402 410
403 memset(&src6, 0, sizeof(src6)); 411 memset(&src6, 0, sizeof(src6));
404 src6.sin6_family = AF_INET6; 412 src6.sin6_family = AF_INET6;
405 src6.sin6_len = sizeof(struct sockaddr_in6); 413 src6.sin6_len = sizeof(struct sockaddr_in6);
406 src6.sin6_addr.s6_addr[10] = src6.sin6_addr.s6_addr[11] = 0xff; 414 src6.sin6_addr.s6_addr[10] = src6.sin6_addr.s6_addr[11] = 0xff;
407 memcpy(&src6.sin6_addr.s6_addr[12], &ip->ip_src, 415 memcpy(&src6.sin6_addr.s6_addr[12], &ip->ip_src,
408 sizeof(ip->ip_src)); 416 sizeof(ip->ip_src));
409 src6.sin6_port = uh->uh_sport; 417 src6.sin6_port = uh->uh_sport;
410 memset(&dst6, 0, sizeof(dst6)); 418 memset(&dst6, 0, sizeof(dst6));
411 dst6.sin6_family = AF_INET6; 419 dst6.sin6_family = AF_INET6;
@@ -1291,27 +1299,27 @@ udp4_espinudp(struct mbuf **mp, int off, @@ -1291,27 +1299,27 @@ udp4_espinudp(struct mbuf **mp, int off,
1291 if ((*mp = m_pullup(m, minlen)) == NULL) { 1299 if ((*mp = m_pullup(m, minlen)) == NULL) {
1292 printf("udp4_espinudp: m_pullup failed\n"); 1300 printf("udp4_espinudp: m_pullup failed\n");
1293 return -1; 1301 return -1;
1294 } 1302 }
1295 m = *mp; 1303 m = *mp;
1296 } 1304 }
1297 1305
1298 len = m->m_len - off; 1306 len = m->m_len - off;
1299 data = mtod(m, char *) + off; 1307 data = mtod(m, char *) + off;
1300 inp = sotoinpcb(so); 1308 inp = sotoinpcb(so);
1301 1309
1302 /* Ignore keepalive packets */ 1310 /* Ignore keepalive packets */
1303 if ((len == 1) && (*(unsigned char *)data == 0xff)) { 1311 if ((len == 1) && (*(unsigned char *)data == 0xff)) {
1304 m_free(m); 1312 m_freem(m);
1305 *mp = NULL; /* avoid any further processiong by caller ... */ 1313 *mp = NULL; /* avoid any further processiong by caller ... */
1306 return 1; 1314 return 1;
1307 } 1315 }
1308 1316
1309 /* 1317 /*
1310 * Check that the payload is long enough to hold 1318 * Check that the payload is long enough to hold
1311 * an ESP header and compute the length of encapsulation 1319 * an ESP header and compute the length of encapsulation
1312 * header to remove 1320 * header to remove
1313 */ 1321 */
1314 if (inp->inp_flags & INP_ESPINUDP) { 1322 if (inp->inp_flags & INP_ESPINUDP) {
1315 u_int32_t *st = (u_int32_t *)data; 1323 u_int32_t *st = (u_int32_t *)data;
1316 1324
1317 if ((len <= sizeof(struct esp)) || (*st == 0)) 1325 if ((len <= sizeof(struct esp)) || (*st == 0))
@@ -1373,27 +1381,28 @@ udp4_espinudp(struct mbuf **mp, int off, @@ -1373,27 +1381,28 @@ udp4_espinudp(struct mbuf **mp, int off,
1373 if ((tag = m_tag_get(PACKET_TAG_IPSEC_NAT_T_PORTS, 1381 if ((tag = m_tag_get(PACKET_TAG_IPSEC_NAT_T_PORTS,
1374 sizeof(sport) + sizeof(dport), M_DONTWAIT)) == NULL) { 1382 sizeof(sport) + sizeof(dport), M_DONTWAIT)) == NULL) {
1375 printf("udp4_espinudp: m_tag_get failed\n"); 1383 printf("udp4_espinudp: m_tag_get failed\n");
1376 m_freem(m); 1384 m_freem(m);
1377 return -1; 1385 return -1;
1378 } 1386 }
1379 ((u_int16_t *)(tag + 1))[0] = sport; 1387 ((u_int16_t *)(tag + 1))[0] = sport;
1380 ((u_int16_t *)(tag + 1))[1] = dport; 1388 ((u_int16_t *)(tag + 1))[1] = dport;
1381 m_tag_prepend(m, tag); 1389 m_tag_prepend(m, tag);
1382 1390
1383#ifdef IPSEC 1391#ifdef IPSEC
1384 if (ipsec_used) 1392 if (ipsec_used)
1385 ipsec4_common_input(m, iphdrlen, IPPROTO_ESP); 1393 ipsec4_common_input(m, iphdrlen, IPPROTO_ESP);
1386 /* XXX: else */ 1394 else
 1395 m_freem(m);
1387#else 1396#else
1388 esp4_input(m, iphdrlen); 1397 esp4_input(m, iphdrlen);
1389#endif 1398#endif
1390 1399
1391 /* We handled it, it shouldn't be handled by UDP */ 1400 /* We handled it, it shouldn't be handled by UDP */
1392 *mp = NULL; /* avoid free by caller ... */ 1401 *mp = NULL; /* avoid free by caller ... */
1393 return 1; 1402 return 1;
1394} 1403}
1395#endif 1404#endif
1396 1405
1397PR_WRAP_USRREQS(udp) 1406PR_WRAP_USRREQS(udp)
1398#define udp_attach udp_attach_wrapper 1407#define udp_attach udp_attach_wrapper
1399#define udp_detach udp_detach_wrapper 1408#define udp_detach udp_detach_wrapper