summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbluhm <bluhm@openbsd.org>2019-04-23 11:01:54 +0000
committerbluhm <bluhm@openbsd.org>2019-04-23 11:01:54 +0000
commitc526b7b24c236da2c46ae923a670d78145f20b73 (patch)
treefef1a77705ae0663cb3aa7bda39fc61fc14d5f84
parenta first cut at converting some virtual ethernet interfaces to if_vinput (diff)
downloadwireguard-openbsd-c526b7b24c236da2c46ae923a670d78145f20b73.tar.xz
wireguard-openbsd-c526b7b24c236da2c46ae923a670d78145f20b73.zip
For raw IPv6 sockets userland may specify an offset where the
checksum field is located. During rip6 input and output make sure that this field is within the packet. The offset my be -1 to disable the feature, otherwise it must be non-negative and aligned. Do a stricter check during setsockopt(2). from FreeBSD; OK claudio@
-rw-r--r--sys/netinet6/ip6_output.c10
-rw-r--r--sys/netinet6/raw_ip6.c15
2 files changed, 19 insertions, 6 deletions
diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c
index fa8927d5f73..7db00f41ffa 100644
--- a/sys/netinet6/ip6_output.c
+++ b/sys/netinet6/ip6_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip6_output.c,v 1.241 2018/12/03 17:25:22 claudio Exp $ */
+/* $OpenBSD: ip6_output.c,v 1.242 2019/04/23 11:01:54 bluhm Exp $ */
/* $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $ */
/*
@@ -1620,8 +1620,12 @@ ip6_raw_ctloutput(int op, struct socket *so, int level, int optname,
break;
}
optval = *mtod(m, int *);
- if ((optval % 2) != 0) {
- /* the API assumes even offset values */
+ if (optval < -1 ||
+ (optval > 0 && (optval % 2) != 0)) {
+ /*
+ * The API assumes non-negative even offset
+ * values or -1 as a special value.
+ */
error = EINVAL;
} else if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) {
if (optval != icmp6off)
diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c
index 1caad919e78..687574617a8 100644
--- a/sys/netinet6/raw_ip6.c
+++ b/sys/netinet6/raw_ip6.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: raw_ip6.c,v 1.135 2019/04/20 11:30:11 bluhm Exp $ */
+/* $OpenBSD: raw_ip6.c,v 1.136 2019/04/23 11:01:54 bluhm Exp $ */
/* $KAME: raw_ip6.c,v 1.69 2001/03/04 15:55:44 itojun Exp $ */
/*
@@ -184,7 +184,16 @@ rip6_input(struct mbuf **mp, int *offp, int proto, int af)
}
if (proto != IPPROTO_ICMPV6 && in6p->inp_cksum6 != -1) {
rip6stat_inc(rip6s_isum);
- if (in6_cksum(m, proto, *offp,
+ /*
+ * Although in6_cksum() does not need the position of
+ * the checksum field for verification, enforce that it
+ * is located within the packet. Userland has given
+ * a checksum offset, a packet too short for that is
+ * invalid. Avoid overflow with user supplied offset.
+ */
+ if (m->m_pkthdr.len < *offp + 2 ||
+ m->m_pkthdr.len - *offp - 2 < in6p->inp_cksum6 ||
+ in6_cksum(m, proto, *offp,
m->m_pkthdr.len - *offp)) {
rip6stat_inc(rip6s_badsum);
continue;
@@ -439,7 +448,7 @@ rip6_output(struct mbuf *m, struct socket *so, struct sockaddr *dstaddr,
off = offsetof(struct icmp6_hdr, icmp6_cksum);
else
off = in6p->inp_cksum6;
- if (plen < off + 1) {
+ if (plen < 2 || plen - 2 < off) {
error = EINVAL;
goto bad;
}