summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2018-02-01 21:11:34 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2018-02-01 21:11:34 +0000
commitcd27a87b337bf98a92c327538d63793d4d32ddce (patch)
tree2ea3f93e8677a68c546a46491ea26ed0f8618ab1 /sys
parentea535cb97f3a7fafc0d7bd950aee42618c3f5c6e (diff)
The function ip6_get_prevhdr() did return a pointer into a mbuf.
It was not guaranteed that the mbuf data was not somewhere else in the chain. So return an offset and do a proper mbuf pulldown. found by Maxime Villard; from NetBSD; with markus@; OK deraadt@
Diffstat (limited to 'sys')
-rw-r--r--sys/netinet6/frag6.c24
-rw-r--r--sys/netinet6/ip6_input.c44
-rw-r--r--sys/netinet6/ip6_var.h4
-rw-r--r--sys/netinet6/raw_ip6.c8
4 files changed, 40 insertions, 40 deletions
diff --git a/sys/netinet6/frag6.c b/sys/netinet6/frag6.c
index 7b874e37bab..f3abef22fa1 100644
--- a/sys/netinet6/frag6.c
+++ b/sys/netinet6/frag6.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: frag6.c,v 1.81 2017/11/14 14:46:49 bluhm Exp $ */
+/* $OpenBSD: frag6.c,v 1.82 2018/02/01 21:11:33 bluhm Exp $ */
/* $KAME: frag6.c,v 1.40 2002/05/27 21:40:31 itojun Exp $ */
/*
@@ -422,14 +422,6 @@ frag6_input(struct mbuf **mp, int *offp, int proto, int af)
goto dropfrag;
}
- /*
- * Store NXT to the original.
- */
- {
- u_int8_t *prvnxtp = ip6_get_prevhdr(m, offset); /* XXX */
- *prvnxtp = nxt;
- }
-
TAILQ_REMOVE(&frag6_queue, q6, ip6q_queue);
frag6_nfrags -= q6->ip6q_nfrag;
frag6_nfragpackets--;
@@ -445,6 +437,20 @@ frag6_input(struct mbuf **mp, int *offp, int proto, int af)
m->m_pkthdr.len = plen;
}
+ /*
+ * Restore NXT to the original.
+ */
+ {
+ int prvnxt = ip6_get_prevhdr(m, offset);
+ uint8_t *prvnxtp;
+
+ IP6_EXTHDR_GET(prvnxtp, uint8_t *, m, prvnxt,
+ sizeof(*prvnxtp));
+ if (prvnxtp == NULL)
+ goto dropfrag;
+ *prvnxtp = nxt;
+ }
+
ip6stat_inc(ip6s_reassembled);
/*
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
index 6f07b36d9d3..b7dc6287e5a 100644
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip6_input.c,v 1.210 2017/11/23 13:45:46 mpi Exp $ */
+/* $OpenBSD: ip6_input.c,v 1.211 2018/02/01 21:11:33 bluhm Exp $ */
/* $KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun Exp $ */
/*
@@ -1188,50 +1188,44 @@ ip6_pullexthdr(struct mbuf *m, size_t off, int nxt)
}
/*
- * Get pointer to the previous header followed by the header
+ * Get offset to the previous header followed by the header
* currently processed.
- * XXX: This function supposes that
- * M includes all headers,
- * the next header field and the header length field of each header
- * are valid, and
- * the sum of each header length equals to OFF.
- * Because of these assumptions, this function must be called very
- * carefully. Moreover, it will not be used in the near future when
- * we develop `neater' mechanism to process extension headers.
*/
-u_int8_t *
+int
ip6_get_prevhdr(struct mbuf *m, int off)
{
struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
- if (off == sizeof(struct ip6_hdr))
- return (&ip6->ip6_nxt);
- else {
- int len, nxt;
- struct ip6_ext *ip6e = NULL;
+ if (off == sizeof(struct ip6_hdr)) {
+ return offsetof(struct ip6_hdr, ip6_nxt);
+ } else if (off < sizeof(struct ip6_hdr)) {
+ panic("%s: off < sizeof(struct ip6_hdr)", __func__);
+ } else {
+ int len, nlen, nxt;
+ struct ip6_ext ip6e;
nxt = ip6->ip6_nxt;
len = sizeof(struct ip6_hdr);
+ nlen = 0;
while (len < off) {
- ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + len);
+ m_copydata(m, len, sizeof(ip6e), (caddr_t)&ip6e);
switch (nxt) {
case IPPROTO_FRAGMENT:
- len += sizeof(struct ip6_frag);
+ nlen = sizeof(struct ip6_frag);
break;
case IPPROTO_AH:
- len += (ip6e->ip6e_len + 2) << 2;
+ nlen = (ip6e.ip6e_len + 2) << 2;
break;
default:
- len += (ip6e->ip6e_len + 1) << 3;
+ nlen = (ip6e.ip6e_len + 1) << 3;
break;
}
- nxt = ip6e->ip6e_nxt;
+ len += nlen;
+ nxt = ip6e.ip6e_nxt;
}
- if (ip6e)
- return (&ip6e->ip6e_nxt);
- else
- return NULL;
+
+ return (len - nlen);
}
}
diff --git a/sys/netinet6/ip6_var.h b/sys/netinet6/ip6_var.h
index 370f23f804b..2e62ac01540 100644
--- a/sys/netinet6/ip6_var.h
+++ b/sys/netinet6/ip6_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip6_var.h,v 1.81 2017/11/05 13:19:59 florian Exp $ */
+/* $OpenBSD: ip6_var.h,v 1.82 2018/02/01 21:11:33 bluhm Exp $ */
/* $KAME: ip6_var.h,v 1.33 2000/06/11 14:59:20 jinmei Exp $ */
/*
@@ -303,7 +303,7 @@ int ip6_input_if(struct mbuf **, int *, int, int, struct ifnet *);
void ip6_freepcbopts(struct ip6_pktopts *);
void ip6_freemoptions(struct ip6_moptions *);
int ip6_unknown_opt(u_int8_t *, struct mbuf *, int);
-u_int8_t *ip6_get_prevhdr(struct mbuf *, int);
+int ip6_get_prevhdr(struct mbuf *, int);
int ip6_nexthdr(struct mbuf *, int, int, int *);
int ip6_lasthdr(struct mbuf *, int, int, int *);
int ip6_mforward(struct ip6_hdr *, struct ifnet *, struct mbuf *);
diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c
index 8824f88987d..464e44090d9 100644
--- a/sys/netinet6/raw_ip6.c
+++ b/sys/netinet6/raw_ip6.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: raw_ip6.c,v 1.125 2017/12/04 13:40:35 bluhm Exp $ */
+/* $OpenBSD: raw_ip6.c,v 1.126 2018/02/01 21:11:33 bluhm Exp $ */
/* $KAME: raw_ip6.c,v 1.69 2001/03/04 15:55:44 itojun Exp $ */
/*
@@ -236,10 +236,10 @@ rip6_input(struct mbuf **mp, int *offp, int proto, int af)
if (proto == IPPROTO_NONE || proto == IPPROTO_ICMPV6) {
m_freem(m);
} else {
- u_int8_t *prvnxtp = ip6_get_prevhdr(m, *offp); /* XXX */
+ int prvnxt = ip6_get_prevhdr(m, *offp);
+
icmp6_error(m, ICMP6_PARAM_PROB,
- ICMP6_PARAMPROB_NEXTHEADER,
- prvnxtp - mtod(m, u_int8_t *));
+ ICMP6_PARAMPROB_NEXTHEADER, prvnxt);
}
counters = counters_enter(&ref, ip6counters);
counters[ip6s_delivered]--;