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);
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"