Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys When reassembling IPv4/IPv6 packets, ensure...
details: https://anonhg.NetBSD.org/src/rev/cfb717f3e6fb
branches: trunk
changeset: 319079:cfb717f3e6fb
user: maxv <maxv%NetBSD.org@localhost>
date: Tue May 15 19:16:38 2018 +0000
description:
When reassembling IPv4/IPv6 packets, ensure each fragment has been subject
to the same IPsec processing. That is to say, that all fragments are ESP,
or AH, or AH+ESP, or none.
The reassembly mechanism can be used both on the wire and inside an IPsec
tunnel, so we need to make sure all fragments of a packet were received
on only one side.
Even though I haven't tried, I believe there are configurations where it
would be possible for an attacker to inject an unencrypted fragment into a
legitimate stream of already-decrypted-and-authenticated fragments.
Typically on IPsec gateways with ESP tunnels, where we can encapsulate
fragments (as opposed to the general case, where we fragment encapsulated
data).
Note, for the record: a funnier thing, under IPv4, would be to send a
zero-sized !MFF fragment at the head of the packet, and manage to trigger
an ICMP error; M_DECRYPTED gets lost by the reassembly, and ICMP will reply
with the packet in clear (not encrypted).
diffstat:
sys/netinet/ip_reass.c | 29 +++++++++++++++++++++--------
sys/netinet6/frag6.c | 15 ++++++++++++---
2 files changed, 33 insertions(+), 11 deletions(-)
diffs (136 lines):
diff -r 36588a0d34d6 -r cfb717f3e6fb sys/netinet/ip_reass.c
--- a/sys/netinet/ip_reass.c Tue May 15 10:23:03 2018 +0000
+++ b/sys/netinet/ip_reass.c Tue May 15 19:16:38 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ip_reass.c,v 1.16 2018/05/03 07:25:49 maxv Exp $ */
+/* $NetBSD: ip_reass.c,v 1.17 2018/05/15 19:16:38 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.16 2018/05/03 07:25:49 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_reass.c,v 1.17 2018/05/15 19:16:38 maxv Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -93,7 +93,8 @@
struct in_addr ipq_src;
struct in_addr ipq_dst;
uint16_t ipq_nfrags; /* frags in this queue entry */
- uint8_t ipq_tos; /* TOS of this fragment */
+ uint8_t ipq_tos; /* TOS of this fragment */
+ int ipq_ipsec; /* IPsec flags */
} ipfr_queue_t;
/*
@@ -217,6 +218,7 @@
struct ip *ip = ipqe->ipqe_ip, *qip;
const int hlen = ip->ip_hl << 2;
struct mbuf *m = ipqe->ipqe_m, *t;
+ int ipsecflags = m->m_flags & (M_DECRYPTED|M_AUTHIPHDR);
ipfr_qent_t *nq, *p, *q;
int i, next;
@@ -269,6 +271,7 @@
fp->ipq_p = ip->ip_p;
fp->ipq_id = ip->ip_id;
fp->ipq_tos = ip->ip_tos;
+ fp->ipq_ipsec = ipsecflags;
fp->ipq_src = ip->ip_src;
fp->ipq_dst = ip->ip_dst;
LIST_INSERT_HEAD(&ip_frags[hash], fp, ipq_q);
@@ -614,6 +617,7 @@
const int hlen = ip->ip_hl << 2;
const int len = ntohs(ip->ip_len);
struct mbuf *m = *m0;
+ int ipsecflags = m->m_flags & (M_DECRYPTED|M_AUTHIPHDR);
ipfr_queue_t *fp;
ipfr_qent_t *ipqe;
u_int hash, off, flen;
@@ -669,11 +673,20 @@
break;
}
- /* Make sure that TOS matches previous fragments. */
- if (fp && fp->ipq_tos != ip->ip_tos) {
- IP_STATINC(IP_STAT_BADFRAGS);
- mutex_exit(&ipfr_lock);
- return EINVAL;
+ if (fp) {
+ /* All fragments must have the same IPsec flags. */
+ if (fp->ipq_ipsec != ipsecflags) {
+ IP_STATINC(IP_STAT_BADFRAGS);
+ mutex_exit(&ipfr_lock);
+ return EINVAL;
+ }
+
+ /* Make sure that TOS matches previous fragments. */
+ if (fp->ipq_tos != ip->ip_tos) {
+ IP_STATINC(IP_STAT_BADFRAGS);
+ mutex_exit(&ipfr_lock);
+ return EINVAL;
+ }
}
/*
diff -r 36588a0d34d6 -r cfb717f3e6fb sys/netinet6/frag6.c
--- a/sys/netinet6/frag6.c Tue May 15 10:23:03 2018 +0000
+++ b/sys/netinet6/frag6.c Tue May 15 19:16:38 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: frag6.c,v 1.73 2018/05/03 07:25:49 maxv Exp $ */
+/* $NetBSD: frag6.c,v 1.74 2018/05/15 19:16:38 maxv Exp $ */
/* $KAME: frag6.c,v 1.40 2002/05/27 21:40:31 itojun Exp $ */
/*
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: frag6.c,v 1.73 2018/05/03 07:25:49 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: frag6.c,v 1.74 2018/05/15 19:16:38 maxv Exp $");
#ifdef _KERNEL_OPT
#include "opt_net_mpsafe.h"
@@ -76,6 +76,7 @@
struct ip6q *ip6q_prev;
int ip6q_unfrglen; /* len of unfragmentable part */
int ip6q_nfrag; /* # of fragments */
+ int ip6q_ipsec; /* IPsec flags */
};
struct ip6asfrag {
@@ -162,6 +163,7 @@
struct ip6q *q6;
struct ip6asfrag *af6, *ip6af, *af6dwn;
int offset = *offp, nxt, i, next;
+ int ipsecflags = m->m_flags & (M_DECRYPTED|M_AUTHIPHDR);
int first_frag = 0;
int fragoff, frgpartlen; /* must be larger than u_int16_t */
struct ifnet *dstifp;
@@ -247,6 +249,13 @@
IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &q6->ip6q_dst))
break;
+ if (q6 != &ip6q) {
+ /* All fragments must have the same IPsec flags. */
+ if (q6->ip6q_ipsec != ipsecflags) {
+ goto dropfrag;
+ }
+ }
+
if (q6 == &ip6q) {
/*
* the first fragment to arrive, create a reassembly queue.
@@ -279,8 +288,8 @@
q6->ip6q_src = ip6->ip6_src;
q6->ip6q_dst = ip6->ip6_dst;
q6->ip6q_unfrglen = -1; /* The 1st fragment has not arrived. */
-
q6->ip6q_nfrag = 0;
+ q6->ip6q_ipsec = ipsecflags;
}
/*
Home |
Main Index |
Thread Index |
Old Index