git: 0fda4ffd6905 - main - netlink: augment group writer with priv(9) argument

From: Gleb Smirnoff <glebius_at_FreeBSD.org>
Date: Sat, 11 Jan 2025 05:00:24 UTC
The branch main has been updated by glebius:

URL: https://cgit.FreeBSD.org/src/commit/?id=0fda4ffd69054217096dd1a40355d97be9a8ab94

commit 0fda4ffd69054217096dd1a40355d97be9a8ab94
Author:     Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2025-01-11 04:55:39 +0000
Commit:     Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2025-01-11 04:55:39 +0000

    netlink: augment group writer with priv(9) argument
    
    This will allow to broadcast messages visible only to priveleged
    subscribers.
    
    Reviewed by:            melifaro
    Differential Revision:  https://reviews.freebsd.org/D48307
---
 sys/netlink/netlink_domain.c         |  8 +++++---
 sys/netlink/netlink_generic.c        |  2 +-
 sys/netlink/netlink_glue.c           |  7 ++++---
 sys/netlink/netlink_message_writer.c |  3 ++-
 sys/netlink/netlink_message_writer.h | 10 ++++++----
 sys/netlink/netlink_sysevent.c       |  2 +-
 sys/netlink/netlink_var.h            |  2 +-
 sys/netlink/route/iface.c            |  5 +++--
 sys/netlink/route/neigh.c            |  2 +-
 sys/netlink/route/nexthop.c          |  4 ++--
 sys/netlink/route/rt.c               |  5 +++--
 11 files changed, 29 insertions(+), 21 deletions(-)

diff --git a/sys/netlink/netlink_domain.c b/sys/netlink/netlink_domain.c
index 922da32bfb6d..45d427f43166 100644
--- a/sys/netlink/netlink_domain.c
+++ b/sys/netlink/netlink_domain.c
@@ -47,7 +47,7 @@
 #include <sys/socketvar.h>
 #include <sys/sysent.h>
 #include <sys/syslog.h>
-#include <sys/priv.h> /* priv_check */
+#include <sys/priv.h>
 #include <sys/uio.h>
 
 #include <netlink/netlink.h>
@@ -225,8 +225,10 @@ nl_send_group(struct nl_writer *nw)
 	NLCTL_RLOCK(ctl);
 
 	CK_LIST_FOREACH(nlp, &ctl->ctl_pcb_head, nl_next) {
-		if (nl_isset_group_locked(nlp, nw->group.id) &&
-		    nlp->nl_proto == nw->group.proto) {
+		if ((nw->group.priv == 0 || priv_check_cred(
+		    nlp->nl_socket->so_cred, nw->group.priv) == 0) &&
+		    nlp->nl_proto == nw->group.proto &&
+		    nl_isset_group_locked(nlp, nw->group.id)) {
 			if (nlp_last != NULL) {
 				struct nl_buf *copy;
 
diff --git a/sys/netlink/netlink_generic.c b/sys/netlink/netlink_generic.c
index 0f960d79f477..623531492173 100644
--- a/sys/netlink/netlink_generic.c
+++ b/sys/netlink/netlink_generic.c
@@ -259,7 +259,7 @@ nlctrl_notify(void *arg __unused, const struct genl_family *gf, int cmd)
 	struct nl_writer nw;
 
 	if (!nl_writer_group(&nw, NLMSG_SMALL, NETLINK_GENERIC, ctrl_group_id,
-	    false)) {
+	    0, false)) {
 		NL_LOG(LOG_DEBUG, "error allocating group writer");
 		return;
 	}
diff --git a/sys/netlink/netlink_glue.c b/sys/netlink/netlink_glue.c
index e550a6013654..0e8fdc0b054c 100644
--- a/sys/netlink/netlink_glue.c
+++ b/sys/netlink/netlink_glue.c
@@ -118,7 +118,7 @@ nl_writer_unicast_stub(struct nl_writer *nw, size_t size, struct nlpcb *nlp,
 
 static bool
 nl_writer_group_stub(struct nl_writer *nw, size_t size, uint16_t protocol,
-    uint16_t group_id, bool waitok)
+    uint16_t group_id, int priv, bool waitok)
 {
 	return (get_stub_writer(nw));
 }
@@ -221,9 +221,10 @@ nl_writer_unicast(struct nl_writer *nw, size_t size, struct nlpcb *nlp,
 
 bool
 nl_writer_group(struct nl_writer *nw, size_t size, uint16_t protocol,
-    uint16_t group_id, bool waitok)
+    uint16_t group_id, int priv, bool waitok)
 {
-	return (_nl->nl_writer_group(nw, size, protocol, group_id, waitok));
+	return (_nl->nl_writer_group(nw, size, protocol, group_id, priv,
+	    waitok));
 }
 
 bool
diff --git a/sys/netlink/netlink_message_writer.c b/sys/netlink/netlink_message_writer.c
index 1aebc4690c2d..8c5b3ec14058 100644
--- a/sys/netlink/netlink_message_writer.c
+++ b/sys/netlink/netlink_message_writer.c
@@ -86,11 +86,12 @@ _nl_writer_unicast(struct nl_writer *nw, size_t size, struct nlpcb *nlp,
 
 bool
 _nl_writer_group(struct nl_writer *nw, size_t size, uint16_t protocol,
-    uint16_t group_id, bool waitok)
+    uint16_t group_id, int priv, bool waitok)
 {
 	*nw = (struct nl_writer){
 		.group.proto = protocol,
 		.group.id = group_id,
+		.group.priv = priv,
 		.cb = nl_send_group,
 	};
 
diff --git a/sys/netlink/netlink_message_writer.h b/sys/netlink/netlink_message_writer.h
index 1655acb53fef..83f925e8d93d 100644
--- a/sys/netlink/netlink_message_writer.h
+++ b/sys/netlink/netlink_message_writer.h
@@ -50,6 +50,7 @@ struct nl_writer {
 		struct {
 			uint16_t	proto;
 			uint16_t	id;
+			int		priv;
 		} group;
 	};
 	u_int		num_messages;	/* Number of messages in the buffer */
@@ -67,7 +68,8 @@ struct nl_writer {
 /* Provide optimized calls to the functions inside the same linking unit */
 
 bool _nl_writer_unicast(struct nl_writer *, size_t, struct nlpcb *nlp, bool);
-bool _nl_writer_group(struct nl_writer *, size_t, uint16_t, uint16_t, bool);
+bool _nl_writer_group(struct nl_writer *, size_t, uint16_t, uint16_t, int,
+    bool);
 bool _nlmsg_flush(struct nl_writer *nw);
 void _nlmsg_ignore_limit(struct nl_writer *nw);
 
@@ -89,9 +91,9 @@ nl_writer_unicast(struct nl_writer *nw, size_t size, struct nlpcb *nlp,
 
 static inline bool
 nl_writer_group(struct nl_writer *nw, size_t size, uint16_t proto,
-    uint16_t group_id, bool waitok)
+    uint16_t group_id, int priv, bool waitok)
 {
-	return (_nl_writer_group(nw, size, proto, group_id, waitok));
+	return (_nl_writer_group(nw, size, proto, group_id, priv, waitok));
 }
 
 static inline bool
@@ -141,7 +143,7 @@ nlmsg_end_dump(struct nl_writer *nw, int error, struct nlmsghdr *hdr)
 /* Provide access to the functions via netlink_glue.c */
 
 bool nl_writer_unicast(struct nl_writer *, size_t, struct nlpcb *, bool waitok);
-bool nl_writer_group(struct nl_writer *, size_t, uint16_t, uint16_t,
+bool nl_writer_group(struct nl_writer *, size_t, uint16_t, uint16_t, int,
     bool waitok);
 bool nlmsg_flush(struct nl_writer *nw);
 void nlmsg_ignore_limit(struct nl_writer *nw);
diff --git a/sys/netlink/netlink_sysevent.c b/sys/netlink/netlink_sysevent.c
index 3359c77fa303..c955ce2e8b45 100644
--- a/sys/netlink/netlink_sysevent.c
+++ b/sys/netlink/netlink_sysevent.c
@@ -82,7 +82,7 @@ sysevent_write(struct sysevent_group *se, const char *subsystem, const char *typ
 {
 	struct nl_writer nw;
 
-	if (!nl_writer_group(&nw, NLMSG_LARGE, NETLINK_GENERIC, se->id,
+	if (!nl_writer_group(&nw, NLMSG_LARGE, NETLINK_GENERIC, se->id, 0,
 	    false)) {
 		NL_LOG(LOG_DEBUG, "error allocating group writer");
 		return;
diff --git a/sys/netlink/netlink_var.h b/sys/netlink/netlink_var.h
index 8efe84e935c3..34cba0b28d27 100644
--- a/sys/netlink/netlink_var.h
+++ b/sys/netlink/netlink_var.h
@@ -187,7 +187,7 @@ struct nl_function_wrapper {
 	bool (*nl_writer_unicast)(struct nl_writer *nw, size_t size,
 	    struct nlpcb *nlp, bool waitok);
 	bool (*nl_writer_group)(struct nl_writer *nw, size_t size,
-	    uint16_t protocol, uint16_t group_id, bool waitok);
+	    uint16_t protocol, uint16_t group_id, int priv, bool waitok);
 	bool (*nlmsg_end_dump)(struct nl_writer *nw, int error, struct nlmsghdr *hdr);
 	int (*nl_modify_ifp_generic)(struct ifnet *ifp, struct nl_parsed_link *lattrs,
 	    const struct nlattr_bmask *bm, struct nl_pstate *npt);
diff --git a/sys/netlink/route/iface.c b/sys/netlink/route/iface.c
index 86b1f8f1b1bc..d856498b975f 100644
--- a/sys/netlink/route/iface.c
+++ b/sys/netlink/route/iface.c
@@ -1386,7 +1386,8 @@ rtnl_handle_ifaddr(void *arg __unused, struct ifaddr *ifa, int cmd)
 	if (!nl_has_listeners(NETLINK_ROUTE, group))
 		return;
 
-	if (!nl_writer_group(&nw, NLMSG_LARGE, NETLINK_ROUTE, group, false)) {
+	if (!nl_writer_group(&nw, NLMSG_LARGE, NETLINK_ROUTE, group, 0,
+	    false)) {
 		NL_LOG(LOG_DEBUG, "error allocating group writer");
 		return;
 	}
@@ -1406,7 +1407,7 @@ rtnl_handle_ifevent(if_t ifp, int nlmsg_type, int if_flags_mask)
 	if (!nl_has_listeners(NETLINK_ROUTE, RTNLGRP_LINK))
 		return;
 
-	if (!nl_writer_group(&nw, NLMSG_LARGE, NETLINK_ROUTE, RTNLGRP_LINK,
+	if (!nl_writer_group(&nw, NLMSG_LARGE, NETLINK_ROUTE, RTNLGRP_LINK, 0,
 	    false)) {
 		NL_LOG(LOG_DEBUG, "error allocating group writer");
 		return;
diff --git a/sys/netlink/route/neigh.c b/sys/netlink/route/neigh.c
index ec58c6140db8..9eaaae263254 100644
--- a/sys/netlink/route/neigh.c
+++ b/sys/netlink/route/neigh.c
@@ -566,7 +566,7 @@ rtnl_lle_event(void *arg __unused, struct llentry *lle, int evt)
 
 	int nlmsgs_type = evt == LLENTRY_RESOLVED ? NL_RTM_NEWNEIGH : NL_RTM_DELNEIGH;
 
-	if (!nl_writer_group(&nw, NLMSG_SMALL, NETLINK_ROUTE, RTNLGRP_NEIGH,
+	if (!nl_writer_group(&nw, NLMSG_SMALL, NETLINK_ROUTE, RTNLGRP_NEIGH, 0,
 	    false)) {
 		NL_LOG(LOG_DEBUG, "error allocating group writer");
 		return;
diff --git a/sys/netlink/route/nexthop.c b/sys/netlink/route/nexthop.c
index 03f1a57fd1e4..30aa3dd72534 100644
--- a/sys/netlink/route/nexthop.c
+++ b/sys/netlink/route/nexthop.c
@@ -554,7 +554,7 @@ delete_unhop(struct unhop_ctl *ctl, struct nlmsghdr *hdr, uint32_t uidx)
 	};
 
 	if (!nl_writer_group(&nw, NLMSG_SMALL, NETLINK_ROUTE, RTNLGRP_NEXTHOP,
-	    false)) {
+	    0, false)) {
 		NL_LOG(LOG_DEBUG, "error allocating message writer");
 		return (ENOMEM);
 	}
@@ -949,7 +949,7 @@ rtnl_handle_newnhop(struct nlmsghdr *hdr, struct nlpcb *nlp,
 	};
 
 	if (!nl_writer_group(&nw, NLMSG_SMALL, NETLINK_ROUTE, RTNLGRP_NEXTHOP,
-	    false)) {
+	    0, false)) {
 		NL_LOG(LOG_DEBUG, "error allocating message writer");
 		return (ENOMEM);
 	}
diff --git a/sys/netlink/route/rt.c b/sys/netlink/route/rt.c
index 14bd73d33411..e90debee46da 100644
--- a/sys/netlink/route/rt.c
+++ b/sys/netlink/route/rt.c
@@ -353,7 +353,8 @@ report_operation(uint32_t fibnum, struct rib_cmd_info *rc,
 	struct nl_writer nw;
 	uint32_t group_id = family_to_group(rt_get_family(rc->rc_rt));
 
-	if (nl_writer_group(&nw, NLMSG_SMALL, NETLINK_ROUTE, group_id, false)) {
+	if (nl_writer_group(&nw, NLMSG_SMALL, NETLINK_ROUTE, group_id, 0,
+	    false)) {
 		struct route_nhop_data rnd = {
 			.rnd_nhop = rc_get_nhop(rc),
 			.rnd_weight = rc->rc_nh_weight,
@@ -1082,7 +1083,7 @@ rtnl_handle_route_event(uint32_t fibnum, const struct rib_cmd_info *rc)
 	};
 
 	uint32_t group_id = family_to_group(family);
-	if (!nl_writer_group(&nw, NLMSG_SMALL, NETLINK_ROUTE, group_id,
+	if (!nl_writer_group(&nw, NLMSG_SMALL, NETLINK_ROUTE, group_id, 0,
 	    false)) {
 		NL_LOG(LOG_DEBUG, "error allocating event buffer");
 		return;