From 04cd74b4cdb1203bc0fbfb85d8490a5b45eadf64 Mon Sep 17 00:00:00 2001 From: Mike Karels Date: Mon, 21 Mar 2022 14:59:13 -0500 Subject: [PATCH] IPv4 multicast: fix netstat -g The vif structure includes fields at the end which are #ifdef KERNEL, causing a mismatch between the structure sizes between kernel and user level. netstat -g failed with an ENOMEM on the sysctl to fetch the vif table. Change the vif sysctl code in ip_mroute to copy out only the user-level-visible portion of each table entry. Reviewed by: bz, wma Differential Revision: https://reviews.freebsd.org/D34627 --- sys/netinet/ip_mroute.c | 11 ++++++++--- sys/netinet/ip_mroute.h | 1 + 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/sys/netinet/ip_mroute.c b/sys/netinet/ip_mroute.c index e6acfd4dcfc7..cc356e3678f3 100644 --- a/sys/netinet/ip_mroute.c +++ b/sys/netinet/ip_mroute.c @@ -2727,18 +2727,23 @@ static SYSCTL_NODE(_net_inet_ip, OID_AUTO, mfctable, static int sysctl_viflist(SYSCTL_HANDLER_ARGS) { - int error; + int error, i; if (req->newptr) return (EPERM); if (V_viftable == NULL) /* XXX unlocked */ return (0); - error = sysctl_wire_old_buffer(req, sizeof(*V_viftable) * MAXVIFS); + error = sysctl_wire_old_buffer(req, MROUTE_VIF_SYSCTL_LEN * MAXVIFS); if (error) return (error); MRW_RLOCK(); - error = SYSCTL_OUT(req, V_viftable, sizeof(*V_viftable) * MAXVIFS); + /* Copy out user-visible portion of vif entry. */ + for (i = 0; i < MAXVIFS; i++) { + error = SYSCTL_OUT(req, &V_viftable[i], MROUTE_VIF_SYSCTL_LEN); + if (error) + break; + } MRW_RUNLOCK(); return (error); } diff --git a/sys/netinet/ip_mroute.h b/sys/netinet/ip_mroute.h index 5ad25b485dfc..aaf87770001e 100644 --- a/sys/netinet/ip_mroute.h +++ b/sys/netinet/ip_mroute.h @@ -265,6 +265,7 @@ struct vif { u_long v_bytes_in; /* # bytes in on interface */ u_long v_bytes_out; /* # bytes out on interface */ #ifdef _KERNEL +#define MROUTE_VIF_SYSCTL_LEN __offsetof(struct vif, v_spin) struct mtx v_spin; /* Spin mutex for pkt stats */ char v_spin_name[32]; #endif