[PATCH] ifdown: really set down all active interfaces

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello,

We've got a bug report of random memory corruption when using kexec.
The test case to reproduce the problem sets up bonding between two
tg3 NICs and transmits some data just before calling kexec to boot
the new kernel. Around one in every one hundred boots would crash
early with different signatures.

We confirmed that the patch below resolves the problem. Please, could
you review and consider it for upstream inclusion?

Thanks,
Leonardo

Before executing the new kernel, kexec disables all network interfaces
to prevent problems like random memory corruption caused by in flight
DMAs.

The current algorithm uses the SIOCGIFCONF to enumerate all interfaces
before shutting them down. However, this ioctl returns only the interfaces
that have an IP address set. This means that in some setups, kexec may
skip interfaces that are up and running. A common example is in bonding,
where the enslaved interfaces are up but may not have an IP address
configured.

This patch replaces SIOCGIFCONF with if_nameindex() to enumerate all
network interfaces available, regardless of having an IP address set
or not.

Signed-off-by: Leonardo Chiquitto <lchiquitto at novell.com>

---
 kexec/ifdown.c |   42 +++++++++++++++++++++---------------------
 1 file changed, 21 insertions(+), 21 deletions(-)

Index: kexec-tools/kexec/ifdown.c
===================================================================
--- kexec-tools.orig/kexec/ifdown.c
+++ kexec-tools/kexec/ifdown.c
@@ -19,8 +19,6 @@ char *v_ifdown = "@(#)ifdown.c  1.11  02
 #include <net/if.h>
 #include <netinet/in.h>
 
-#define MAX_IFS	64
-
 /*
  *	First, we find all shaper devices and down them. Then we
  *	down all real interfaces. This is because the comment in the
@@ -29,43 +27,45 @@ char *v_ifdown = "@(#)ifdown.c  1.11  02
  */
 int ifdown(void)
 {
-	struct ifreq ifr[MAX_IFS];
-	struct ifconf ifc;
-	int i, fd;
-	int numif;
-	int shaper;
+	struct if_nameindex *ifa, *ifp;
+	struct ifreq ifr;
+	int fd, shaper;
 
 	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
 		fprintf(stderr, "ifdown: ");
 		perror("socket");
 		return -1;
 	}
-	ifc.ifc_len = sizeof(ifr);
-	ifc.ifc_req = ifr;
 
-	if (ioctl(fd, SIOCGIFCONF, &ifc) < 0) {
+	if ((ifa = if_nameindex()) == NULL) {
 		fprintf(stderr, "ifdown: ");
-		perror("SIOCGIFCONF");
-		close(fd);
+		perror("if_nameindex");
 		return -1;
 	}
-	numif = ifc.ifc_len / sizeof(struct ifreq);
 
 	for (shaper = 1; shaper >= 0; shaper--) {
-		for (i = 0; i < numif; i++) {
+		for (ifp = ifa; ifp->if_index; ifp++) {
 
-			if ((strncmp(ifr[i].ifr_name, "shaper", 6) == 0)
+			if ((strncmp(ifp->if_name, "shaper", 6) == 0)
 			    != shaper) continue;
-
-			if (strcmp(ifr[i].ifr_name, "lo") == 0)
+			if (strcmp(ifp->if_name, "lo") == 0)
 				continue;
-			if (strchr(ifr[i].ifr_name, ':') != NULL)
+			if (strchr(ifp->if_name, ':') != NULL)
 				continue;
-			ifr[i].ifr_flags &= ~(IFF_UP);
-			if (ioctl(fd, SIOCSIFFLAGS, &ifr[i]) < 0) {
+
+			strncpy(ifr.ifr_name, ifp->if_name, IFNAMSIZ);
+			if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
 				fprintf(stderr, "ifdown: shutdown ");
-				perror(ifr[i].ifr_name);
+				perror(ifp->if_name);
+				return -1;
 			}
+			ifr.ifr_flags &= ~(IFF_UP);
+			if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) {
+				fprintf(stderr, "ifdown: shutdown ");
+				perror(ifp->if_name);
+				return -1;
+			}
+
 		}
 	}
 	close(fd);



[Index of Archives]     [LM Sensors]     [Linux Sound]     [ALSA Users]     [ALSA Devel]     [Linux Audio Users]     [Linux Media]     [Kernel]     [Gimp]     [Yosemite News]     [Linux Media]

  Powered by Linux