Blame SOURCES/0001-fcoemon-netlink-buffer-resize-fix.patch

b56cc0
From 3b4ca6b87dae6b11da137b6afb4cf8275687d281 Mon Sep 17 00:00:00 2001
b56cc0
From: Chris Leech <cleech@redhat.com>
b56cc0
Date: Thu, 24 Jan 2019 18:16:47 -0800
b56cc0
Subject: [PATCH] fcoemon: netlink buffer resize fix
b56cc0
b56cc0
The recv buffer resizing for netlink messages looks to have always been
b56cc0
busted, it discards some of the data in the process of increasing the
b56cc0
buffer size.
b56cc0
b56cc0
I've recently seen issues where the size of the netlink attributes in a
b56cc0
GETLINK request hit the fcm_link_buf_size window and some of the network
b56cc0
interfaces were ignored by fcoemon (happened mostly with recent kernels,
b56cc0
2 dual-port bnx2 NICs, bonding for LAN traffic on 2 ports and FCoE on
b56cc0
the other 2).  When the ignored interface happens to be the one you want
b56cc0
to use for FCoE, it never gets fixed.
b56cc0
b56cc0
This fixes the buffer resize code to use MSG_PEEK|MSG_TRUNC to check for
b56cc0
the needed buffer size first, and then resize with realloc when needed.
b56cc0
This might not actually be needed, with an 8k buffer I don't think the
b56cc0
kernel side will send more at once until after it sees the application
b56cc0
post a larger buffer, but I did force a resize and see that it worked.
b56cc0
b56cc0
Signed-off-by: Chris Leech <cleech@redhat.com>
b56cc0
---
b56cc0
 fcoemon.c | 54 ++++++++++++++++++------------------------------------
b56cc0
 1 file changed, 18 insertions(+), 36 deletions(-)
b56cc0
b56cc0
diff --git a/fcoemon.c b/fcoemon.c
b56cc0
index 9a400c56b72..9af0f1284af 100644
b56cc0
--- a/fcoemon.c
b56cc0
+++ b/fcoemon.c
b56cc0
@@ -328,7 +328,6 @@ static int fcm_link_socket;
b56cc0
 static int fcm_link_seq;
b56cc0
 static void fcm_link_recv(void *);
b56cc0
 static void fcm_link_getlink(void);
b56cc0
-static int fcm_link_buf_check(size_t);
b56cc0
 static void clear_dcbd_info(struct fcm_netif *ff);
b56cc0
 static int fcoe_vid_from_ifname(const char *ifname);
b56cc0
 
b56cc0
@@ -354,8 +353,7 @@ char progname[20];
b56cc0
  * large enough to fit and expand it if we ever do a read that almost fills it.
b56cc0
  */
b56cc0
 static char *fcm_link_buf;
b56cc0
-static size_t fcm_link_buf_size = 4096;	/* initial size */
b56cc0
-static const size_t fcm_link_buf_fuzz = 300;	/* "almost full" remainder */
b56cc0
+static size_t fcm_link_buf_size = 8192;	/* initial size */
b56cc0
 
b56cc0
 /*
b56cc0
  * A value must be surrounded by quates, e.g. "x".
b56cc0
@@ -1848,8 +1846,22 @@ static void fcm_link_recv(UNUSED void *arg)
b56cc0
 	size_t plen;
b56cc0
 	size_t rlen;
b56cc0
 
b56cc0
+	/* check to make sure our receive buffer is large enough,
b56cc0
+	 * or scale it up as needed */
b56cc0
+	rc = recv(fcm_link_socket, NULL, 0, MSG_PEEK | MSG_TRUNC);
b56cc0
+	if (rc > fcm_link_buf_size) {
b56cc0
+		FCM_LOG_DBG("resizing link buf to %d bytes\n", rc);
b56cc0
+		void *resize = realloc(fcm_link_buf, rc);
b56cc0
+		if (resize) {
b56cc0
+			fcm_link_buf = resize;
b56cc0
+			fcm_link_buf_size = rc;
b56cc0
+		} else {
b56cc0
+			FCM_LOG_ERR(errno, "Failed to allocate link buffer");
b56cc0
+		}
b56cc0
+	}
b56cc0
+
b56cc0
 	buf = fcm_link_buf;
b56cc0
-	rc = read(fcm_link_socket, buf, fcm_link_buf_size);
b56cc0
+	rc = recv(fcm_link_socket, buf, fcm_link_buf_size, 0);
b56cc0
 	if (rc <= 0) {
b56cc0
 		if (rc < 0)
b56cc0
 			FCM_LOG_ERR(errno, "Error reading from "
b56cc0
@@ -1858,11 +1870,6 @@ static void fcm_link_recv(UNUSED void *arg)
b56cc0
 		return;
b56cc0
 	}
b56cc0
 
b56cc0
-	if (fcm_link_buf_check(rc)) {
b56cc0
-		fcm_link_getlink();
b56cc0
-		return;
b56cc0
-	}
b56cc0
-
b56cc0
 	hp = (struct nlmsghdr *)buf;
b56cc0
 	rlen = rc;
b56cc0
 	for (hp = (struct nlmsghdr *)buf; NLMSG_OK(hp, rlen);
b56cc0
@@ -1927,34 +1934,9 @@ static void fcm_link_getlink(void)
b56cc0
 	msg.nl.nlmsg_pid = getpid();
b56cc0
 	msg.ifi.ifi_family = AF_UNSPEC;
b56cc0
 	msg.ifi.ifi_type = ARPHRD_ETHER;
b56cc0
-	rc = write(fcm_link_socket, &msg, sizeof(msg));
b56cc0
+	rc = send(fcm_link_socket, &msg, sizeof(msg), 0);
b56cc0
 	if (rc < 0)
b56cc0
-		FCM_LOG_ERR(errno, "write error");
b56cc0
-}
b56cc0
-
b56cc0
-/*
b56cc0
- * Check for whether buffer needs to grow based on amount read.
b56cc0
- * Free's the old buffer so don't use that after this returns non-zero.
b56cc0
- */
b56cc0
-static int fcm_link_buf_check(size_t read_len)
b56cc0
-{
b56cc0
-	char *buf;
b56cc0
-	size_t len = read_len;
b56cc0
-
b56cc0
-	if (len > fcm_link_buf_size - fcm_link_buf_fuzz) {
b56cc0
-		len = fcm_link_buf_size;
b56cc0
-		len = len + len / 2;	/* grow by 50% */
b56cc0
-		buf = malloc(len);
b56cc0
-		if (buf != NULL) {
b56cc0
-			free(fcm_link_buf);
b56cc0
-			fcm_link_buf = buf;
b56cc0
-			fcm_link_buf_size = len;
b56cc0
-			return 1;
b56cc0
-		} else {
b56cc0
-			FCM_LOG_ERR(errno, "failed to allocate link buffer");
b56cc0
-		}
b56cc0
-	}
b56cc0
-	return 0;
b56cc0
+		FCM_LOG_ERR(errno, "send error");
b56cc0
 }
b56cc0
 
b56cc0
 static void fcm_fcoe_init(void)
b56cc0
-- 
b56cc0
2.21.0
b56cc0