naccyde / rpms / iproute

Forked from rpms/iproute 10 months ago
Clone

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

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