git: 72b97a4e2861 - stable/14 - netlink: cope with growing requests

From: Kristof Provost <kp_at_FreeBSD.org>
Date: Tue, 24 Oct 2023 12:27:49 UTC
The branch stable/14 has been updated by kp:

URL: https://cgit.FreeBSD.org/src/commit/?id=72b97a4e28617b600cc21eb51664d1e1f6e6f923

commit 72b97a4e28617b600cc21eb51664d1e1f6e6f923
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2023-10-16 09:48:57 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2023-10-24 07:45:20 +0000

    netlink: cope with growing requests
    
    If a request ends up growing beyong the initially allocated space the
    netlink functions (such as snl_add_msg_attr_u32()) will allocate a
    new buffer. This invalidates the header pointer we can have received
    from snl_create_msg_request(). Always use the hdr returned by
    snl_finalize_msg().
    
    Reviewed by:    melifaro
    MFC after:      1 week
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
    Differential Revision:  https://reviews.freebsd.org/D42223
    
    (cherry picked from commit 4f8f43b06ed07e96a250855488cc531799d5b78f)
---
 sbin/ifconfig/af_inet.c              |  6 +++---
 sbin/ifconfig/af_inet6.c             |  2 +-
 sbin/ifconfig/ifconfig_netlink.c     |  6 +++---
 sbin/route/route_netlink.c           |  8 ++++----
 sys/netlink/netlink_snl_generic.h    |  2 +-
 tests/sys/netlink/test_snl_generic.c |  2 +-
 usr.sbin/arp/arp_netlink.c           | 12 ++++++------
 usr.sbin/ndp/ndp_netlink.c           | 12 ++++++------
 8 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/sbin/ifconfig/af_inet.c b/sbin/ifconfig/af_inet.c
index 83b605e8c4cb..bcf2a8ab0ffd 100644
--- a/sbin/ifconfig/af_inet.c
+++ b/sbin/ifconfig/af_inet.c
@@ -360,7 +360,7 @@ in_delete_first_nl(if_ctx *ctx)
 	ifahdr->ifa_family = AF_INET;
 	ifahdr->ifa_index = ifindex;
 
-	if (!snl_finalize_msg(&nw) || !snl_send_message(ss, hdr))
+	if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ss, hdr))
 		return (EINVAL);
 
 	nlmsg_seq = hdr->nlmsg_seq;
@@ -391,7 +391,7 @@ in_delete_first_nl(if_ctx *ctx)
 	ifahdr->ifa_index = ifindex;
 	snl_add_msg_attr_ip4(&nw, IFA_LOCAL, &addr);
 
-	if (!snl_finalize_msg(&nw) || !snl_send_message(ss, hdr))
+	if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ss, hdr))
 		return (EINVAL);
 	memset(&e, 0, sizeof(e));
 	snl_read_reply_code(ss, hdr->nlmsg_seq, &e);
@@ -431,7 +431,7 @@ in_exec_nl(if_ctx *ctx, unsigned long action, void *data)
 		snl_add_msg_attr_u32(&nw, IFAF_VHID, pdata->vhid);
 	snl_end_attr_nested(&nw, off);
 
-	if (!snl_finalize_msg(&nw) || !snl_send_message(ctx->io_ss, hdr))
+	if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ctx->io_ss, hdr))
 		return (0);
 
 	struct snl_errmsg_data e = {};
diff --git a/sbin/ifconfig/af_inet6.c b/sbin/ifconfig/af_inet6.c
index a0138e9b3de6..b3da21758982 100644
--- a/sbin/ifconfig/af_inet6.c
+++ b/sbin/ifconfig/af_inet6.c
@@ -493,7 +493,7 @@ in6_exec_nl(if_ctx *ctx, unsigned long action, void *data)
 		snl_add_msg_attr_u32(&nw, IFAF_VHID, pdata->vhid);
 	snl_end_attr_nested(&nw, off);
 
-	if (!snl_finalize_msg(&nw) || !snl_send_message(ctx->io_ss, hdr))
+	if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ctx->io_ss, hdr))
 		return (0);
 
 	struct snl_errmsg_data e = {};
diff --git a/sbin/ifconfig/ifconfig_netlink.c b/sbin/ifconfig/ifconfig_netlink.c
index 76dd99307f31..7be340e18ab5 100644
--- a/sbin/ifconfig/ifconfig_netlink.c
+++ b/sbin/ifconfig/ifconfig_netlink.c
@@ -171,7 +171,7 @@ prepare_ifmap(struct snl_state *ss)
 	hdr->nlmsg_flags |= NLM_F_DUMP;
 	snl_reserve_msg_object(&nw, struct ifinfomsg);
 
-	if (!snl_finalize_msg(&nw) || !snl_send_message(ss, hdr))
+	if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ss, hdr))
 		return (NULL);
 
 	uint32_t nlmsg_seq = hdr->nlmsg_seq;
@@ -212,7 +212,7 @@ if_nametoindex_nl(struct snl_state *ss, const char *ifname)
 	snl_reserve_msg_object(&nw, struct ifinfomsg);
 	snl_add_msg_attr_string(&nw, IFLA_IFNAME, ifname);
 
-	if (!snl_finalize_msg(&nw) || !snl_send_message(ss, hdr))
+	if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ss, hdr))
 		return (0);
 
 	hdr = snl_read_reply(ss, hdr->nlmsg_seq);
@@ -234,7 +234,7 @@ prepare_ifaddrs(struct snl_state *ss, struct ifmap *ifmap)
 	hdr->nlmsg_flags |= NLM_F_DUMP;
 	snl_reserve_msg_object(&nw, struct ifaddrmsg);
 
-	if (!snl_finalize_msg(&nw) || !snl_send_message(ss, hdr))
+	if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ss, hdr))
 		return;
 
 	uint32_t nlmsg_seq = hdr->nlmsg_seq;
diff --git a/sbin/route/route_netlink.c b/sbin/route/route_netlink.c
index 0dbd90151e10..28766b062e18 100644
--- a/sbin/route/route_netlink.c
+++ b/sbin/route/route_netlink.c
@@ -266,7 +266,7 @@ rtmsg_nl_int(struct nl_helper *h, int cmd, int rtm_flags, int fib, int rtm_addrs
 	if (rt_metrics->rmx_weight > 0)
 		snl_add_msg_attr_u32(&nw, NL_RTA_WEIGHT, rt_metrics->rmx_weight);
 
-	if (snl_finalize_msg(&nw) && snl_send_message(ss, hdr)) {
+	if ((hdr = snl_finalize_msg(&nw)) && snl_send_message(ss, hdr)) {
 		struct snl_errmsg_data e = {};
 
 		hdr = snl_read_reply(ss, hdr->nlmsg_seq);
@@ -314,7 +314,7 @@ get_ifdata(struct nl_helper *h, uint32_t ifindex, struct snl_parsed_link_simple
 	struct ifinfomsg *ifmsg = snl_reserve_msg_object(&nw, struct ifinfomsg);
 	if (ifmsg != NULL)
 		ifmsg->ifi_index = ifindex;
-	if (!snl_finalize_msg(&nw) || !snl_send_message(ss, hdr))
+	if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ss, hdr))
 		return;
 
 	hdr = snl_read_reply(ss, hdr->nlmsg_seq);
@@ -817,7 +817,7 @@ flushroute_one(struct nl_helper *h, struct snl_parsed_route *r)
 	snl_add_msg_attr_u32(&nw, RTA_TABLE, r->rta_table);
 	snl_add_msg_attr_ip(&nw, RTA_DST, r->rta_dst);
 
-	if (!snl_finalize_msg(&nw) || !snl_send_message(ss, hdr))
+	if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ss, hdr))
 		return (ENOMEM);
 
 	if (!snl_read_reply_code(ss, hdr->nlmsg_seq, &e)) {
@@ -864,7 +864,7 @@ flushroutes_fib_nl(int fib, int af)
 	rtm->rtm_family = af;
 	snl_add_msg_attr_u32(&nw, RTA_TABLE, fib);
 
-	if (!snl_finalize_msg(&nw) || !snl_send_message(&ss, hdr)) {
+	if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(&ss, hdr)) {
 		snl_free(&ss);
 		return (EINVAL);
 	}
diff --git a/sys/netlink/netlink_snl_generic.h b/sys/netlink/netlink_snl_generic.h
index 1324cf3da17a..0a2913c9155e 100644
--- a/sys/netlink/netlink_snl_generic.h
+++ b/sys/netlink/netlink_snl_generic.h
@@ -106,7 +106,7 @@ snl_get_genl_family_info(struct snl_state *ss, const char *family_name,
 	snl_init_writer(ss, &nw);
 	hdr = snl_create_genl_msg_request(&nw, GENL_ID_CTRL, CTRL_CMD_GETFAMILY);
 	snl_add_msg_attr_string(&nw, CTRL_ATTR_FAMILY_NAME, family_name);
-	if (snl_finalize_msg(&nw) == NULL || !snl_send_message(ss, hdr))
+	if ((hdr = snl_finalize_msg(&nw)) == NULL || !snl_send_message(ss, hdr))
 		return (false);
 
 	hdr = snl_read_reply(ss, hdr->nlmsg_seq);
diff --git a/tests/sys/netlink/test_snl_generic.c b/tests/sys/netlink/test_snl_generic.c
index f3c11daf19e1..d84d3f88f487 100644
--- a/tests/sys/netlink/test_snl_generic.c
+++ b/tests/sys/netlink/test_snl_generic.c
@@ -86,7 +86,7 @@ ATF_TC_BODY(test_snl_get_genl_family_groups, tc)
 	snl_init_writer(&ss, &nw);
 	hdr = snl_create_genl_msg_request(&nw, GENL_ID_CTRL, CTRL_CMD_GETFAMILY);
 	snl_add_msg_attr_string(&nw, CTRL_ATTR_FAMILY_NAME, "nlctrl");
-	snl_finalize_msg(&nw);
+	hdr = snl_finalize_msg(&nw);
 	snl_send_message(&ss, hdr);
 
 	hdr = snl_read_reply(&ss, hdr->nlmsg_seq);
diff --git a/usr.sbin/arp/arp_netlink.c b/usr.sbin/arp/arp_netlink.c
index 40b5367f330d..d78f380af04b 100644
--- a/usr.sbin/arp/arp_netlink.c
+++ b/usr.sbin/arp/arp_netlink.c
@@ -63,7 +63,7 @@ get_link_info(struct snl_state *ss, uint32_t ifindex,
 	struct ifinfomsg *ifmsg = snl_reserve_msg_object(&nw, struct ifinfomsg);
 	if (ifmsg != NULL)
 		ifmsg->ifi_index = ifindex;
-	if (!snl_finalize_msg(&nw) || !snl_send_message(ss, hdr))
+	if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ss, hdr))
 		return (false);
 
 	hdr = snl_read_reply(ss, hdr->nlmsg_seq);
@@ -116,7 +116,7 @@ guess_ifindex(struct snl_state *ss, uint32_t fibnum, struct in_addr addr)
 	snl_add_msg_attr_ip(&nw, RTA_DST, (struct sockaddr *)&dst);
 	snl_add_msg_attr_u32(&nw, RTA_TABLE, fibnum);
 
-	if (!snl_finalize_msg(&nw) || !snl_send_message(ss, hdr))
+	if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ss, hdr))
 		return (0);
 
 	hdr = snl_read_reply(ss, hdr->nlmsg_seq);
@@ -148,7 +148,7 @@ guess_ifindex(struct snl_state *ss, uint32_t fibnum, struct in_addr addr)
 	snl_add_msg_attr_u32(&nw, NHAF_TABLE, fibnum);
 	snl_end_attr_nested(&nw, off);
 
-	if (!snl_finalize_msg(&nw) || !snl_send_message(ss, hdr))
+	if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ss, hdr))
 		return (0);
 
 	hdr = snl_read_reply(ss, hdr->nlmsg_seq);
@@ -285,7 +285,7 @@ print_entries_nl(uint32_t ifindex, struct in_addr addr)
 		ndmsg->ndm_ifindex = ifindex;
 	}
 
-	if (!snl_finalize_msg(&nw) || !snl_send_message(&ss_req, hdr)) {
+	if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(&ss_req, hdr)) {
 		snl_free(&ss_req);
 		return (0);
 	}
@@ -355,7 +355,7 @@ delete_nl(uint32_t ifindex, char *host)
 	}
 	snl_add_msg_attr_ip(&nw, NDA_DST, (struct sockaddr *)dst);
 
-	if (!snl_finalize_msg(&nw) || !snl_send_message(&ss, hdr)) {
+	if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(&ss, hdr)) {
 		snl_free(&ss);
 		return (1);
 	}
@@ -422,7 +422,7 @@ set_nl(uint32_t ifindex, struct sockaddr_in *dst, struct sockaddr_dl *sdl, char
 		snl_end_attr_nested(&nw, off);
 	}
 
-	if (!snl_finalize_msg(&nw) || !snl_send_message(&ss, hdr)) {
+	if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(&ss, hdr)) {
 		snl_free(&ss);
 		return (1);
 	}
diff --git a/usr.sbin/ndp/ndp_netlink.c b/usr.sbin/ndp/ndp_netlink.c
index 954d16995b5a..79bdec2356d0 100644
--- a/usr.sbin/ndp/ndp_netlink.c
+++ b/usr.sbin/ndp/ndp_netlink.c
@@ -76,7 +76,7 @@ get_link_info(struct snl_state *ss, uint32_t ifindex,
 	struct ifinfomsg *ifmsg = snl_reserve_msg_object(&nw, struct ifinfomsg);
 	if (ifmsg != NULL)
 		ifmsg->ifi_index = ifindex;
-	if (!snl_finalize_msg(&nw) || !snl_send_message(ss, hdr))
+	if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ss, hdr))
 		return (false);
 
 	hdr = snl_read_reply(ss, hdr->nlmsg_seq);
@@ -152,7 +152,7 @@ guess_ifindex(struct snl_state *ss, uint32_t fibnum, const struct sockaddr_in6 *
 	snl_add_msg_attr_ip(&nw, RTA_DST, (struct sockaddr *)dst);
 	snl_add_msg_attr_u32(&nw, RTA_TABLE, fibnum);
 
-	if (!snl_finalize_msg(&nw) || !snl_send_message(ss, hdr))
+	if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ss, hdr))
 		return (0);
 
 	hdr = snl_read_reply(ss, hdr->nlmsg_seq);
@@ -184,7 +184,7 @@ guess_ifindex(struct snl_state *ss, uint32_t fibnum, const struct sockaddr_in6 *
 	snl_add_msg_attr_u32(&nw, NHAF_TABLE, fibnum);
 	snl_end_attr_nested(&nw, off);
 
-	if (!snl_finalize_msg(&nw) || !snl_send_message(ss, hdr))
+	if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ss, hdr))
 		return (0);
 
 	hdr = snl_read_reply(ss, hdr->nlmsg_seq);
@@ -327,7 +327,7 @@ print_entries_nl(uint32_t ifindex, struct sockaddr_in6 *addr, bool cflag)
 		ndmsg->ndm_ifindex = ifindex;
 	}
 
-	if (!snl_finalize_msg(&nw) || !snl_send_message(&ss_req, hdr)) {
+	if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(&ss_req, hdr)) {
 		snl_free(&ss_req);
 		return (0);
 	}
@@ -421,7 +421,7 @@ delete_nl(uint32_t ifindex, char *host)
 	}
 	snl_add_msg_attr_ip(&nw, NDA_DST, (struct sockaddr *)&dst);
 
-	if (!snl_finalize_msg(&nw) || !snl_send_message(&ss, hdr)) {
+	if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(&ss, hdr)) {
 		snl_free(&ss);
 		return (1);
 	}
@@ -493,7 +493,7 @@ set_nl(uint32_t ifindex, struct sockaddr_in6 *dst, struct sockaddr_dl *sdl, char
 	snl_add_msg_attr_ip(&nw, NDA_DST, (struct sockaddr *)dst);
 	snl_add_msg_attr(&nw, NDA_LLADDR, sdl->sdl_alen, LLADDR(sdl));
 
-	if (!snl_finalize_msg(&nw) || !snl_send_message(&ss, hdr)) {
+	if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(&ss, hdr)) {
 		snl_free(&ss);
 		return (1);
 	}