naccyde / rpms / iproute

Forked from rpms/iproute 5 months ago
Clone

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

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