diff mbox series

[iproute2,2/3] rdma: stat: fix memory leak in res_counter_line()

Message ID 09e775d1152bc4c92722e91098de01b752a4e7cd.1643736038.git.aclaudi@redhat.com (mailing list archive)
State Changes Requested
Delegated to: Stephen Hemminger
Headers show
Series some memory leak fixes | expand

Checks

Context Check Description
netdev/tree_selection success Not a local patch

Commit Message

Andrea Claudi Feb. 1, 2022, 5:39 p.m. UTC
get_task_name() uses asprintf() to reserve storage for the task name
string. As asprintf() manpage states, a free() should be used to release
the allocated storage when it is no longer needed.

res_counter_line() uses get_task_name() but does not free the allocated
storage on the error paths and after the usage.

This uses a single return point to free the allocated storage, adopting
the same approach of other rdma code using get_task_name().

Fixes: 5937552b42e4 ("rdma: Add "stat qp show" support")
Signed-off-by: Andrea Claudi <aclaudi@redhat.com>
---
 rdma/stat.c | 74 ++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 50 insertions(+), 24 deletions(-)
diff mbox series

Patch

diff --git a/rdma/stat.c b/rdma/stat.c
index adfcd34a..66121b12 100644
--- a/rdma/stat.c
+++ b/rdma/stat.c
@@ -222,9 +222,9 @@  static int res_counter_line(struct rd *rd, const char *name, int index,
 	uint32_t cntn, port = 0, pid = 0, qpn, qp_type = 0;
 	struct nlattr *hwc_table, *qp_table;
 	struct nlattr *nla_entry;
-	const char *comm = NULL;
+	char *comm = NULL;
 	bool isfirst;
-	int err;
+	int err, ret;
 
 	if (nla_line[RDMA_NLDEV_ATTR_PORT_INDEX])
 		port = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_PORT_INDEX]);
@@ -232,52 +232,70 @@  static int res_counter_line(struct rd *rd, const char *name, int index,
 	hwc_table = nla_line[RDMA_NLDEV_ATTR_STAT_HWCOUNTERS];
 	qp_table = nla_line[RDMA_NLDEV_ATTR_RES_QP];
 	if (!hwc_table || !qp_table ||
-	    !nla_line[RDMA_NLDEV_ATTR_STAT_COUNTER_ID])
-		return MNL_CB_ERROR;
+	    !nla_line[RDMA_NLDEV_ATTR_STAT_COUNTER_ID]) {
+		ret = MNL_CB_ERROR;
+		goto out;
+	}
 
 	cntn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_STAT_COUNTER_ID]);
 	if (rd_is_filtered_attr(rd, "cntn", cntn,
-				nla_line[RDMA_NLDEV_ATTR_STAT_COUNTER_ID]))
-		return MNL_CB_OK;
+				nla_line[RDMA_NLDEV_ATTR_STAT_COUNTER_ID])) {
+		ret = MNL_CB_OK;
+		goto out;
+	}
 
 	if (nla_line[RDMA_NLDEV_ATTR_RES_TYPE])
 		qp_type = mnl_attr_get_u8(nla_line[RDMA_NLDEV_ATTR_RES_TYPE]);
 
 	if (rd_is_string_filtered_attr(rd, "qp-type", qp_types_to_str(qp_type),
-				       nla_line[RDMA_NLDEV_ATTR_RES_TYPE]))
-		return MNL_CB_OK;
+				       nla_line[RDMA_NLDEV_ATTR_RES_TYPE])) {
+		ret = MNL_CB_OK;
+		goto out;
+	}
 
 	if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) {
 		pid = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_PID]);
 		comm = get_task_name(pid);
 	}
 	if (rd_is_filtered_attr(rd, "pid", pid,
-				nla_line[RDMA_NLDEV_ATTR_RES_PID]))
-		return MNL_CB_OK;
+				nla_line[RDMA_NLDEV_ATTR_RES_PID])) {
+		ret = MNL_CB_OK;
+		goto out;
+	}
 
-	if (nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])
+	if (nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]) {
+		/* discard const from mnl_attr_get_str */
 		comm = (char *)mnl_attr_get_str(
 			nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]);
+	}
 
 	mnl_attr_for_each_nested(nla_entry, qp_table) {
 		struct nlattr *qp_line[RDMA_NLDEV_ATTR_MAX] = {};
 
 		err = mnl_attr_parse_nested(nla_entry, rd_attr_cb, qp_line);
-		if (err != MNL_CB_OK)
-			return -EINVAL;
+		if (err != MNL_CB_OK) {
+			ret = -EINVAL;
+			goto out;
+		}
 
-		if (!qp_line[RDMA_NLDEV_ATTR_RES_LQPN])
-			return -EINVAL;
+		if (!qp_line[RDMA_NLDEV_ATTR_RES_LQPN]) {
+			ret = -EINVAL;
+			goto out;
+		}
 
 		qpn = mnl_attr_get_u32(qp_line[RDMA_NLDEV_ATTR_RES_LQPN]);
 		if (rd_is_filtered_attr(rd, "lqpn", qpn,
-					qp_line[RDMA_NLDEV_ATTR_RES_LQPN]))
-			return MNL_CB_OK;
+					qp_line[RDMA_NLDEV_ATTR_RES_LQPN])) {
+			ret = MNL_CB_OK;
+			goto out;
+		}
 	}
 
 	err = res_get_hwcounters(rd, hwc_table, false);
-	if (err != MNL_CB_OK)
-		return err;
+	if (err != MNL_CB_OK) {
+		ret = err;
+		goto out;
+	}
 	open_json_object(NULL);
 	print_link(rd, index, name, port, nla_line);
 	print_color_uint(PRINT_ANY, COLOR_NONE, "cntn", "cntn %u ", cntn);
@@ -292,11 +310,15 @@  static int res_counter_line(struct rd *rd, const char *name, int index,
 	mnl_attr_for_each_nested(nla_entry, qp_table) {
 		struct nlattr *qp_line[RDMA_NLDEV_ATTR_MAX] = {};
 		err = mnl_attr_parse_nested(nla_entry, rd_attr_cb, qp_line);
-		if (err != MNL_CB_OK)
-			return -EINVAL;
+		if (err != MNL_CB_OK) {
+			ret = -EINVAL;
+			goto out;
+		}
 
-		if (!qp_line[RDMA_NLDEV_ATTR_RES_LQPN])
-			return -EINVAL;
+		if (!qp_line[RDMA_NLDEV_ATTR_RES_LQPN]) {
+			ret = -EINVAL;
+			goto out;
+		}
 
 		qpn = mnl_attr_get_u32(qp_line[RDMA_NLDEV_ATTR_RES_LQPN]);
 		if (!isfirst)
@@ -307,7 +329,11 @@  static int res_counter_line(struct rd *rd, const char *name, int index,
 	}
 	close_json_array(PRINT_ANY, ">");
 	newline(rd);
-	return MNL_CB_OK;
+	ret = MNL_CB_OK;
+out:
+	if (nla_line[RDMA_NLDEV_ATTR_RES_PID])
+		free(comm);
+	return ret;
 }
 
 static int stat_qp_show_parse_cb(const struct nlmsghdr *nlh, void *data)