summaryrefslogtreecommitdiff
path: root/sys/netinet/ip_mroute.c
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2024-04-06 14:23:28 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2024-04-06 14:23:28 +0000
commita6fc509dacb6ee685d1eeb20c41d8993f7369c9b (patch)
tree7ad44469e898c15927ef16b73243f115d2889ed7 /sys/netinet/ip_mroute.c
parentde67e679224b59adc382c26f491fc06e0b3593c6 (diff)
IP multicast sysctl mrtmfc must not write outside of allocation.
Reading sysctl mrt_sysctl_mfc() allocates memory to be copied back to user. Chunks of struct mfcinfo are copied from routing table to linear heap memory. If the allocated memory was not a multiple the struct size, a struct mfcinfo could be copied to a partially unallocated destination. Check that the end of the struct is within the allocation. From Alfredo Ortega; OK claudio@
Diffstat (limited to 'sys/netinet/ip_mroute.c')
-rw-r--r--sys/netinet/ip_mroute.c21
1 files changed, 10 insertions, 11 deletions
diff --git a/sys/netinet/ip_mroute.c b/sys/netinet/ip_mroute.c
index 3e9b00ec265..1913b1767a1 100644
--- a/sys/netinet/ip_mroute.c
+++ b/sys/netinet/ip_mroute.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_mroute.c,v 1.141 2024/02/11 18:14:26 mvs Exp $ */
+/* $OpenBSD: ip_mroute.c,v 1.142 2024/04/06 14:23:27 bluhm Exp $ */
/* $NetBSD: ip_mroute.c,v 1.85 2004/04/26 01:31:57 matt Exp $ */
/*
@@ -430,8 +430,9 @@ mrt_rtwalk_mfcsysctl(struct rtentry *rt, void *arg, unsigned int rtableid)
}
for (minfo = msa->msa_minfos;
- (uint8_t *)minfo < ((uint8_t *)msa->msa_minfos + msa->msa_len);
- minfo++) {
+ (uint8_t *)(minfo + 1) <=
+ (uint8_t *)msa->msa_minfos + msa->msa_len;
+ minfo++) {
/* Find a new entry or update old entry. */
if (minfo->mfc_origin.s_addr !=
satosin(rt->rt_gateway)->sin_addr.s_addr ||
@@ -471,13 +472,11 @@ mrt_sysctl_mfc(void *oldp, size_t *oldlenp)
if (oldp != NULL && *oldlenp > MAXPHYS)
return (EINVAL);
- if (oldp != NULL)
+ memset(&msa, 0, sizeof(msa));
+ if (oldp != NULL && *oldlenp > 0) {
msa.msa_minfos = malloc(*oldlenp, M_TEMP, M_WAITOK | M_ZERO);
- else
- msa.msa_minfos = NULL;
-
- msa.msa_len = *oldlenp;
- msa.msa_needed = 0;
+ msa.msa_len = *oldlenp;
+ }
for (rtableid = 0; rtableid <= RT_TABLEID_MAX; rtableid++) {
rtable_walk(rtableid, AF_INET, NULL, mrt_rtwalk_mfcsysctl,
@@ -486,11 +485,11 @@ mrt_sysctl_mfc(void *oldp, size_t *oldlenp)
if (msa.msa_minfos != NULL && msa.msa_needed > 0 &&
(error = copyout(msa.msa_minfos, oldp, msa.msa_needed)) != 0) {
- free(msa.msa_minfos, M_TEMP, *oldlenp);
+ free(msa.msa_minfos, M_TEMP, msa.msa_len);
return (error);
}
- free(msa.msa_minfos, M_TEMP, *oldlenp);
+ free(msa.msa_minfos, M_TEMP, msa.msa_len);
*oldlenp = msa.msa_needed;
return (0);