diff options
author | 2019-04-23 11:01:54 +0000 | |
---|---|---|
committer | 2019-04-23 11:01:54 +0000 | |
commit | c526b7b24c236da2c46ae923a670d78145f20b73 (patch) | |
tree | fef1a77705ae0663cb3aa7bda39fc61fc14d5f84 | |
parent | a first cut at converting some virtual ethernet interfaces to if_vinput (diff) | |
download | wireguard-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.c | 10 | ||||
-rw-r--r-- | sys/netinet6/raw_ip6.c | 15 |
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; } |