naccyde / rpms / iproute

Forked from rpms/iproute 5 months ago
Clone
Blob Blame History Raw
From 3ec32595e21849de3165d52e1af48ca3bdf51fab Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Thu, 25 Oct 2018 12:24:30 +0200
Subject: [PATCH] libnetlink: fix leak and using unused memory on error

Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1602555
Upstream Status: iproute2.git commit c60389e4f9ea8

commit c60389e4f9ea88d7246dbb148d28791d577fe5b4
Author: Stephen Hemminger <stephen@networkplumber.org>
Date:   Thu Sep 13 12:33:38 2018 -0700

    libnetlink: fix leak and using unused memory on error

    If an error happens in multi-segment message (tc only)
    then report the error and stop processing further responses.
    This also fixes refering to the buffer after free.

    The sequence check is not necessary here because the
    response message has already been validated to be in
    the window of the sequence number of the iov.

    Reported-by: Mahesh Bandewar <mahesh@bandewar.net>
    Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
    Acked-by: Mahesh Bandewar <maheshb@google.com>
---
 lib/libnetlink.c | 23 +++++++++--------------
 1 file changed, 9 insertions(+), 14 deletions(-)

diff --git a/lib/libnetlink.c b/lib/libnetlink.c
index 928de1d..5868092 100644
--- a/lib/libnetlink.c
+++ b/lib/libnetlink.c
@@ -617,7 +617,6 @@ static int __rtnl_talk_iov(struct rtnl_handle *rtnl, struct iovec *iov,
 	msg.msg_iovlen = 1;
 	i = 0;
 	while (1) {
-next:
 		status = rtnl_recvmsg(rtnl->fd, &msg, &buf);
 		++i;
 
@@ -660,27 +659,23 @@ next:
 
 				if (l < sizeof(struct nlmsgerr)) {
 					fprintf(stderr, "ERROR truncated\n");
-				} else if (!err->error) {
+					free(buf);
+					return -1;
+				}
+
+				if (!err->error)
 					/* check messages from kernel */
 					nl_dump_ext_ack(h, errfn);
 
-					if (answer)
-						*answer = (struct nlmsghdr *)buf;
-					else
-						free(buf);
-					if (h->nlmsg_seq == seq)
-						return 0;
-					else if (i < iovlen)
-						goto next;
-					return 0;
-				}
-
 				if (rtnl->proto != NETLINK_SOCK_DIAG &&
 				    show_rtnl_err)
 					rtnl_talk_error(h, err, errfn);
 
 				errno = -err->error;
-				free(buf);
+				if (answer)
+					*answer = (struct nlmsghdr *)buf;
+				else
+					free(buf);
 				return -i;
 			}
 
-- 
1.8.3.1