Date: Fri, 1 Mar 2019 18:47:41 +0000 (UTC) From: Michael Tuexen <tuexen@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r344708 - head/sys/netinet Message-ID: <201903011847.x21Ilfhm086213@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: tuexen Date: Fri Mar 1 18:47:41 2019 New Revision: 344708 URL: https://svnweb.freebsd.org/changeset/base/344708 Log: Honor the memory limits provided when processing the IPPROTO_SCTP level socket option SCTP_GET_LOCAL_ADDRESSES in a getsockopt() call. Thanks to Thomas Barabosch for reporting the issue which was found by running syzkaller. MFC after: 3 days Modified: head/sys/netinet/sctp_usrreq.c Modified: head/sys/netinet/sctp_usrreq.c ============================================================================== --- head/sys/netinet/sctp_usrreq.c Fri Mar 1 18:12:07 2019 (r344707) +++ head/sys/netinet/sctp_usrreq.c Fri Mar 1 18:47:41 2019 (r344708) @@ -1122,12 +1122,18 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp, } #ifdef INET6 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) { + if (actual + sizeof(struct sockaddr_in6) > limit) { + return (actual); + } in6_sin_2_v4mapsin6(sin, (struct sockaddr_in6 *)sas); ((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport; sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(struct sockaddr_in6)); actual += sizeof(struct sockaddr_in6); } else { #endif + if (actual + sizeof(struct sockaddr_in) > limit) { + return (actual); + } memcpy(sas, sin, sizeof(struct sockaddr_in)); ((struct sockaddr_in *)sas)->sin_port = inp->sctp_lport; sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(struct sockaddr_in)); @@ -1135,9 +1141,6 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp, #ifdef INET6 } #endif - if (actual >= limit) { - return (actual); - } } else { continue; } @@ -1182,13 +1185,13 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp, (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) { continue; } + if (actual + sizeof(struct sockaddr_in6) > limit) { + return (actual); + } memcpy(sas, sin6, sizeof(struct sockaddr_in6)); ((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport; sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(struct sockaddr_in6)); actual += sizeof(struct sockaddr_in6); - if (actual >= limit) { - return (actual); - } } else { continue; } @@ -1202,6 +1205,7 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp, } } else { struct sctp_laddr *laddr; + size_t sa_len; LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { if (stcb) { @@ -1209,6 +1213,10 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp, continue; } } + sa_len = laddr->ifa->address.sa.sa_len; + if (actual + sa_len > limit) { + return (actual); + } if (sctp_fill_user_address(sas, &laddr->ifa->address.sa)) continue; switch (laddr->ifa->address.sa.sa_family) { @@ -1226,12 +1234,8 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp, /* TSNH */ break; } - sas = (struct sockaddr_storage *)((caddr_t)sas + - laddr->ifa->address.sa.sa_len); - actual += laddr->ifa->address.sa.sa_len; - if (actual >= limit) { - return (actual); - } + sas = (struct sockaddr_storage *)((caddr_t)sas + sa_len); + actual += sa_len; } } return (actual);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201903011847.x21Ilfhm086213>