changeset 5491:6cd47402148f draft

privsep: We now need to carry ifa_data for BSD
author Roy Marples <roy@marples.name>
date Wed, 30 Sep 2020 17:25:32 +0100
parents df4ea0197ce8
children 9fe902232341
files src/privsep-root.c
diffstat 1 files changed, 41 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/src/privsep-root.c	Wed Sep 30 16:14:39 2020 +0100
+++ b/src/privsep-root.c	Wed Sep 30 17:25:32 2020 +0100
@@ -346,15 +346,14 @@
 #endif
 
 #ifdef PRIVSEP_GETIFADDRS
-#define	IFA_NADDRS	3
+#define	IFA_NADDRS	4
 static ssize_t
 ps_root_dogetifaddrs(void **rdata, size_t *rlen)
 {
-	struct ifaddrs *ifaddrs, *ifa, *ifa_next;
+	struct ifaddrs *ifaddrs, *ifa;
 	size_t len;
 	uint8_t *buf, *sap;
 	socklen_t salen;
-	void *ifa_data;
 
 	if (getifaddrs(&ifaddrs) == -1)
 		return -1;
@@ -380,6 +379,15 @@
 			len += ALIGN(sa_len(ifa->ifa_netmask));
 		if (ifa->ifa_broadaddr != NULL)
 			len += ALIGN(sa_len(ifa->ifa_broadaddr));
+#ifdef BSD
+		/*
+		 * On BSD we need to carry ifa_data so we can access
+		 * if_data->ifi_link_state
+		 */
+		if (ifa->ifa_addr != NULL &&
+		    ifa->ifa_addr->sa_family == AF_LINK)
+			len += ALIGN(sizeof(struct if_data));
+#endif
 	}
 
 	/* Use calloc to set everything to zero.
@@ -394,15 +402,8 @@
 	*rlen = len;
 
 	for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
-		/* Don't carry ifa_data or ifa_next. */
-		ifa_data = ifa->ifa_data;
-		ifa_next = ifa->ifa_next;
-		ifa->ifa_data = NULL;
-		ifa->ifa_next = NULL;
 		memcpy(buf, ifa, sizeof(*ifa));
 		buf += ALIGN(sizeof(*ifa));
-		ifa->ifa_data = ifa_data;
-		ifa->ifa_next = ifa_next;
 
 		strlcpy((char *)buf, ifa->ifa_name, IFNAMSIZ);
 		buf += ALIGN(IFNAMSIZ);
@@ -411,7 +412,10 @@
 
 #define	COPYINSA(addr)						\
 	do {							\
-		salen = sa_len((addr));				\
+		if ((addr) != NULL)				\
+			salen = sa_len((addr));			\
+		else						\
+			salen = 0;				\
 		if (salen != 0) {				\
 			memcpy(sap, &salen, sizeof(salen));	\
 			memcpy(buf, (addr), salen);		\
@@ -420,12 +424,21 @@
 		sap += sizeof(salen);				\
 	} while (0 /*CONSTCOND */)
 
-		if (ifa->ifa_addr != NULL)
-			COPYINSA(ifa->ifa_addr);
-		if (ifa->ifa_netmask != NULL)
-			COPYINSA(ifa->ifa_netmask);
-		if (ifa->ifa_broadaddr != NULL)
-			COPYINSA(ifa->ifa_broadaddr);
+		COPYINSA(ifa->ifa_addr);
+		COPYINSA(ifa->ifa_netmask);
+		COPYINSA(ifa->ifa_broadaddr);
+
+#ifdef BSD
+		if (ifa->ifa_addr != NULL &&
+		    ifa->ifa_addr->sa_family == AF_LINK)
+		{
+			salen = (socklen_t)sizeof(struct if_data);
+			memcpy(buf, ifa->ifa_data, salen);
+			buf += ALIGN(salen);
+		} else
+#endif
+			salen = 0;
+		memcpy(sap, &salen, sizeof(salen));
 	}
 
 	freeifaddrs(ifaddrs);
@@ -948,6 +961,17 @@
 		COPYOUTSA(ifa->ifa_addr);
 		COPYOUTSA(ifa->ifa_netmask);
 		COPYOUTSA(ifa->ifa_broadaddr);
+
+		memcpy(&salen, sap, sizeof(salen));
+		if (len < salen)
+			goto err;
+		if (salen != 0) {
+			ifa->ifa_data = bp;
+			bp += ALIGN(salen);
+			len -= ALIGN(salen);
+		} else
+			ifa->ifa_data = NULL;
+
 		if (len != 0)
 			ifa->ifa_next = (struct ifaddrs *)(void *)bp;
 		else