Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 130701790bf2d95e902edf16031ff596 > files > 61

autofs-5.0.1-0.rc2.164.el5_8.src.rpm

autofs-5.0.3 - fix interface config buffer size

From: Ian Kent <raven@themaw.net>

When getting the interface configuration information autofs uses a
fixed size buffer for the interface information. If there are many
interfaces this causes the check to fail.
---

 modules/replicated.c |   51 ++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 43 insertions(+), 8 deletions(-)


diff --git a/modules/replicated.c b/modules/replicated.c
index 362ab1b..ad1ede2 100644
--- a/modules/replicated.c
+++ b/modules/replicated.c
@@ -95,6 +95,41 @@ void seed_random(void)
 	return;
 }
 
+static int alloc_ifreq(struct ifconf *ifc, int sock)
+{
+	int ret, lastlen = 0, len = MAX_IFC_BUF;
+	char err_buf[MAX_ERR_BUF], *buf;
+
+	while (1) {
+		buf = malloc(len);
+		if (!buf) {
+			char *estr = strerror_r(errno, err_buf, MAX_ERR_BUF);
+			logerr("malloc: %s", estr);
+			return 0;
+		}
+
+		ifc->ifc_len = sizeof(buf);
+		ifc->ifc_req = (struct ifreq *) buf;
+
+		ret = ioctl(sock, SIOCGIFCONF, ifc);
+		if (ret == -1) {
+			char *estr = strerror_r(errno, err_buf, MAX_ERR_BUF);
+			logerr("ioctl: %s", estr);
+			free(buf);
+			return 0;
+		}
+
+		if (ifc->ifc_len == lastlen)
+			break;
+
+		lastlen = ifc->ifc_len;
+		len += MAX_IFC_BUF;
+		free(buf);
+	}
+
+	return 1;
+}
+
 static unsigned int get_proximity(const char *host_addr, int addr_len)
 {
 	struct sockaddr_in *msk_addr, *if_addr;
@@ -122,12 +157,7 @@ static unsigned int get_proximity(const char *host_addr, int addr_len)
 		fcntl(sock, F_SETFD, cl_flags);
 	}
 
-	ifc.ifc_len = sizeof(buf);
-	ifc.ifc_req = (struct ifreq *) buf;
-	ret = ioctl(sock, SIOCGIFCONF, &ifc);
-	if (ret == -1) {
-		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		logerr("ioctl: %s", estr);
+	if (!alloc_ifreq(&ifc, sock)) {
 		close(sock);
 		return PROXIMITY_ERROR;
 	}
@@ -138,7 +168,7 @@ static unsigned int get_proximity(const char *host_addr, int addr_len)
 	i = 0;
 	ptr = (char *) &ifc.ifc_buf[0];
 
-	while (ptr < buf + ifc.ifc_len) {
+	while (ptr < (char *) ifc.ifc_req + ifc.ifc_len) {
 		ifr = (struct ifreq *) ptr;
 
 		switch (ifr->ifr_addr.sa_family) {
@@ -147,6 +177,7 @@ static unsigned int get_proximity(const char *host_addr, int addr_len)
 			ret = memcmp(&if_addr->sin_addr, hst_addr, addr_len);
 			if (!ret) {
 				close(sock);
+				free(ifc.ifc_req);
 				return PROXIMITY_LOCAL;
 			}
 			break;
@@ -162,7 +193,7 @@ static unsigned int get_proximity(const char *host_addr, int addr_len)
 	i = 0;
 	ptr = (char *) &ifc.ifc_buf[0];
 
-	while (ptr < buf + ifc.ifc_len) {
+	while (ptr < (char *) ifc.ifc_req + ifc.ifc_len) {
 		ifr = (struct ifreq *) ptr;
 
 		switch (ifr->ifr_addr.sa_family) {
@@ -178,6 +209,7 @@ static unsigned int get_proximity(const char *host_addr, int addr_len)
 				char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
 				logerr("ioctl: %s", estr);
 				close(sock);
+				free(ifc.ifc_req);
 				return PROXIMITY_ERROR;
 			}
 
@@ -186,6 +218,7 @@ static unsigned int get_proximity(const char *host_addr, int addr_len)
 
 			if ((ia & mask) == (ha & mask)) {
 				close(sock);
+				free(ifc.ifc_req);
 				return PROXIMITY_SUBNET;
 			}
 
@@ -208,6 +241,7 @@ static unsigned int get_proximity(const char *host_addr, int addr_len)
 
 			if ((ia & mask) == (ha & mask)) {
 				close(sock);
+				free(ifc.ifc_req);
 				return PROXIMITY_NET;
 			}
 			break;
@@ -221,6 +255,7 @@ static unsigned int get_proximity(const char *host_addr, int addr_len)
 	}
 
 	close(sock);
+	free(ifc.ifc_req);
 
 	return PROXIMITY_OTHER;
 }