Blame SOURCES/0022-lib-libnetlink-re-malloc-buff-if-size-is-not-enough.patch

36cfb7
From 49e7c0e7c8c9a982fd3aa69bbed4e306a1dcb331 Mon Sep 17 00:00:00 2001
36cfb7
From: Hangbin Liu <haliu@redhat.com>
36cfb7
Date: Wed, 8 Nov 2017 14:39:12 +0800
36cfb7
Subject: [PATCH] lib/libnetlink: re malloc buff if size is not enough
36cfb7
36cfb7
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1380803
36cfb7
Upstream Status: iproute2.git net-next commit 2d34851cd341
36cfb7
36cfb7
commit 2d34851cd341f0e1b3fc17ca3e6e874229f3a1f8
36cfb7
Author: Hangbin Liu <liuhangbin@gmail.com>
36cfb7
Date:   Thu Oct 26 09:41:46 2017 +0800
36cfb7
36cfb7
    lib/libnetlink: re malloc buff if size is not enough
36cfb7
36cfb7
    With commit 72b365e8e0fd ("libnetlink: Double the dump buffer size")
36cfb7
    we doubled the buffer size to support more VFs. But the VFs number is
36cfb7
    increasing all the time. Some customers even use more than 200 VFs now.
36cfb7
36cfb7
    We could not double it everytime when the buffer is not enough. Let's just
36cfb7
    not hard code the buffer size and malloc the correct number when running.
36cfb7
36cfb7
    Introduce function rtnl_recvmsg() to always return a newly allocated buffer.
36cfb7
    The caller need to free it after using.
36cfb7
36cfb7
    Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
36cfb7
    Signed-off-by: Phil Sutter <phil@nwl.cc>
36cfb7
36cfb7
Signed-off-by: Hangbin Liu <haliu@redhat.com>
36cfb7
---
36cfb7
 lib/libnetlink.c | 114 ++++++++++++++++++++++++++++++++++++++-----------------
36cfb7
 1 file changed, 80 insertions(+), 34 deletions(-)
36cfb7
36cfb7
diff --git a/lib/libnetlink.c b/lib/libnetlink.c
36cfb7
index a057831..446c960 100644
36cfb7
--- a/lib/libnetlink.c
36cfb7
+++ b/lib/libnetlink.c
36cfb7
@@ -386,6 +386,64 @@ static void rtnl_dump_error(const struct rtnl_handle *rth,
36cfb7
 	}
36cfb7
 }
36cfb7
 
36cfb7
+static int __rtnl_recvmsg(int fd, struct msghdr *msg, int flags)
36cfb7
+{
36cfb7
+	int len;
36cfb7
+
36cfb7
+	do {
36cfb7
+		len = recvmsg(fd, msg, flags);
36cfb7
+	} while (len < 0 && (errno == EINTR || errno == EAGAIN));
36cfb7
+
36cfb7
+	if (len < 0) {
36cfb7
+		fprintf(stderr, "netlink receive error %s (%d)\n",
36cfb7
+			strerror(errno), errno);
36cfb7
+		return -errno;
36cfb7
+	}
36cfb7
+
36cfb7
+	if (len == 0) {
36cfb7
+		fprintf(stderr, "EOF on netlink\n");
36cfb7
+		return -ENODATA;
36cfb7
+	}
36cfb7
+
36cfb7
+	return len;
36cfb7
+}
36cfb7
+
36cfb7
+static int rtnl_recvmsg(int fd, struct msghdr *msg, char **answer)
36cfb7
+{
36cfb7
+	struct iovec *iov = msg->msg_iov;
36cfb7
+	char *buf;
36cfb7
+	int len;
36cfb7
+
36cfb7
+	iov->iov_base = NULL;
36cfb7
+	iov->iov_len = 0;
36cfb7
+
36cfb7
+	len = __rtnl_recvmsg(fd, msg, MSG_PEEK | MSG_TRUNC);
36cfb7
+	if (len < 0)
36cfb7
+		return len;
36cfb7
+
36cfb7
+	buf = malloc(len);
36cfb7
+	if (!buf) {
36cfb7
+		fprintf(stderr, "malloc error: not enough buffer\n");
36cfb7
+		return -ENOMEM;
36cfb7
+	}
36cfb7
+
36cfb7
+	iov->iov_base = buf;
36cfb7
+	iov->iov_len = len;
36cfb7
+
36cfb7
+	len = __rtnl_recvmsg(fd, msg, 0);
36cfb7
+	if (len < 0) {
36cfb7
+		free(buf);
36cfb7
+		return len;
36cfb7
+	}
36cfb7
+
36cfb7
+	if (answer)
36cfb7
+		*answer = buf;
36cfb7
+	else
36cfb7
+		free(buf);
36cfb7
+
36cfb7
+	return len;
36cfb7
+}
36cfb7
+
36cfb7
 int rtnl_dump_filter_l(struct rtnl_handle *rth,
36cfb7
 		       const struct rtnl_dump_filter_arg *arg)
36cfb7
 {
36cfb7
@@ -397,31 +455,18 @@ int rtnl_dump_filter_l(struct rtnl_handle *rth,
36cfb7
 		.msg_iov = &iov,
36cfb7
 		.msg_iovlen = 1,
36cfb7
 	};
36cfb7
-	char buf[32768];
36cfb7
+	char *buf;
36cfb7
 	int dump_intr = 0;
36cfb7
 
36cfb7
-	iov.iov_base = buf;
36cfb7
 	while (1) {
36cfb7
 		int status;
36cfb7
 		const struct rtnl_dump_filter_arg *a;
36cfb7
 		int found_done = 0;
36cfb7
 		int msglen = 0;
36cfb7
 
36cfb7
-		iov.iov_len = sizeof(buf);
36cfb7
-		status = recvmsg(rth->fd, &msg, 0);
36cfb7
-
36cfb7
-		if (status < 0) {
36cfb7
-			if (errno == EINTR || errno == EAGAIN)
36cfb7
-				continue;
36cfb7
-			fprintf(stderr, "netlink receive error %s (%d)\n",
36cfb7
-				strerror(errno), errno);
36cfb7
-			return -1;
36cfb7
-		}
36cfb7
-
36cfb7
-		if (status == 0) {
36cfb7
-			fprintf(stderr, "EOF on netlink\n");
36cfb7
-			return -1;
36cfb7
-		}
36cfb7
+		status = rtnl_recvmsg(rth->fd, &msg, &buf;;
36cfb7
+		if (status < 0)
36cfb7
+			return status;
36cfb7
 
36cfb7
 		if (rth->dump_fp)
36cfb7
 			fwrite(buf, 1, NLMSG_ALIGN(status), rth->dump_fp);
36cfb7
@@ -446,8 +491,10 @@ int rtnl_dump_filter_l(struct rtnl_handle *rth,
36cfb7
 
36cfb7
 				if (h->nlmsg_type == NLMSG_DONE) {
36cfb7
 					err = rtnl_dump_done(h);
36cfb7
-					if (err < 0)
36cfb7
+					if (err < 0) {
36cfb7
+						free(buf);
36cfb7
 						return -1;
36cfb7
+					}
36cfb7
 
36cfb7
 					found_done = 1;
36cfb7
 					break; /* process next filter */
36cfb7
@@ -455,19 +502,23 @@ int rtnl_dump_filter_l(struct rtnl_handle *rth,
36cfb7
 
36cfb7
 				if (h->nlmsg_type == NLMSG_ERROR) {
36cfb7
 					rtnl_dump_error(rth, h);
36cfb7
+					free(buf);
36cfb7
 					return -1;
36cfb7
 				}
36cfb7
 
36cfb7
 				if (!rth->dump_fp) {
36cfb7
 					err = a->filter(&nladdr, h, a->arg1);
36cfb7
-					if (err < 0)
36cfb7
+					if (err < 0) {
36cfb7
+						free(buf);
36cfb7
 						return err;
36cfb7
+					}
36cfb7
 				}
36cfb7
 
36cfb7
 skip_it:
36cfb7
 				h = NLMSG_NEXT(h, msglen);
36cfb7
 			}
36cfb7
 		}
36cfb7
+		free(buf);
36cfb7
 
36cfb7
 		if (found_done) {
36cfb7
 			if (dump_intr)
36cfb7
@@ -527,7 +578,7 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
36cfb7
 		.msg_iov = &iov,
36cfb7
 		.msg_iovlen = 1,
36cfb7
 	};
36cfb7
-	char   buf[32768] = {};
36cfb7
+	char *buf;
36cfb7
 
36cfb7
 	n->nlmsg_seq = seq = ++rtnl->seq;
36cfb7
 
36cfb7
@@ -540,22 +591,12 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
36cfb7
 		return -1;
36cfb7
 	}
36cfb7
 
36cfb7
-	iov.iov_base = buf;
36cfb7
 	while (1) {
36cfb7
-		iov.iov_len = sizeof(buf);
36cfb7
-		status = recvmsg(rtnl->fd, &msg, 0);
36cfb7
+		status = rtnl_recvmsg(rtnl->fd, &msg, &buf;;
36cfb7
+
36cfb7
+		if (status < 0)
36cfb7
+			return status;
36cfb7
 
36cfb7
-		if (status < 0) {
36cfb7
-			if (errno == EINTR || errno == EAGAIN)
36cfb7
-				continue;
36cfb7
-			fprintf(stderr, "netlink receive error %s (%d)\n",
36cfb7
-				strerror(errno), errno);
36cfb7
-			return -1;
36cfb7
-		}
36cfb7
-		if (status == 0) {
36cfb7
-			fprintf(stderr, "EOF on netlink\n");
36cfb7
-			return -1;
36cfb7
-		}
36cfb7
 		if (msg.msg_namelen != sizeof(nladdr)) {
36cfb7
 			fprintf(stderr,
36cfb7
 				"sender address length == %d\n",
36cfb7
@@ -569,6 +610,7 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
36cfb7
 			if (l < 0 || len > status) {
36cfb7
 				if (msg.msg_flags & MSG_TRUNC) {
36cfb7
 					fprintf(stderr, "Truncated message\n");
36cfb7
+					free(buf);
36cfb7
 					return -1;
36cfb7
 				}
36cfb7
 				fprintf(stderr,
36cfb7
@@ -595,6 +637,7 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
36cfb7
 					if (answer)
36cfb7
 						memcpy(answer, h,
36cfb7
 						       MIN(maxlen, h->nlmsg_len));
36cfb7
+					free(buf);
36cfb7
 					return 0;
36cfb7
 				}
36cfb7
 
36cfb7
@@ -603,12 +646,14 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
36cfb7
 					rtnl_talk_error(h, err, errfn);
36cfb7
 
36cfb7
 				errno = -err->error;
36cfb7
+				free(buf);
36cfb7
 				return -1;
36cfb7
 			}
36cfb7
 
36cfb7
 			if (answer) {
36cfb7
 				memcpy(answer, h,
36cfb7
 				       MIN(maxlen, h->nlmsg_len));
36cfb7
+				free(buf);
36cfb7
 				return 0;
36cfb7
 			}
36cfb7
 
36cfb7
@@ -617,6 +662,7 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
36cfb7
 			status -= NLMSG_ALIGN(len);
36cfb7
 			h = (struct nlmsghdr *)((char *)h + NLMSG_ALIGN(len));
36cfb7
 		}
36cfb7
+		free(buf);
36cfb7
 
36cfb7
 		if (msg.msg_flags & MSG_TRUNC) {
36cfb7
 			fprintf(stderr, "Message truncated\n");
36cfb7
-- 
36cfb7
1.8.3.1
36cfb7