Commit dd6da24822 for strongswan.org

commit dd6da24822dc5022471a334d22209060bf660d4d
Author: Tobias Brunner <tobias@strongswan.org>
Date:   Mon Nov 9 14:12:48 2026 +0100

    kernel-netlink: Explicitly reject non-kernel responses

    A privileged process could theoretically inject responses.  As only the
    kernel can send messages from `nl_pid` 0, this check prevents that.

    Also fixed the error handling where the comparison converted `-1` to
    `size_t` and previously caused an error to trigger the "exceeds buffer
    size" path (no behavior change other than the log message).

diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c
index a38f6bd8a2..59b107fc1d 100644
--- a/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c
+++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c
@@ -234,6 +234,8 @@ static bool write_msg(private_netlink_socket_t *this, struct nlmsghdr *msg)
 static ssize_t read_msg(private_netlink_socket_t *this,
 						char *buf, size_t buflen, bool block)
 {
+	struct sockaddr_nl addr = {};
+	socklen_t addr_len = sizeof(addr);
 	ssize_t len;

 	if (block)
@@ -251,12 +253,9 @@ static ssize_t read_msg(private_netlink_socket_t *this,
 			return -1;
 		}
 	}
-	len = recv(this->socket, buf, buflen, MSG_TRUNC|(block ? 0 : MSG_DONTWAIT));
-	if (len > buflen)
-	{
-		DBG1(DBG_KNL, "netlink response exceeds buffer size");
-		return 0;
-	}
+	len = recvfrom(this->socket, buf, buflen,
+				   MSG_TRUNC|(block ? 0 : MSG_DONTWAIT),
+				   (struct sockaddr*)&addr, &addr_len);
 	if (len < 0)
 	{
 		if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)
@@ -265,6 +264,15 @@ static ssize_t read_msg(private_netlink_socket_t *this,
 		}
 		return 0;
 	}
+	else if (len > buflen)
+	{
+		DBG1(DBG_KNL, "netlink response exceeds buffer size");
+		return 0;
+	}
+	else if (addr.nl_pid != 0)
+	{	/* ignore non-kernel messages */
+		return 0;
+	}
 	return len;
 }

@@ -748,7 +756,7 @@ CALLBACK(watch_event, bool,
 {
 	char buf[this->buflen];
 	struct nlmsghdr *hdr = (struct nlmsghdr*)buf;
-	struct sockaddr_nl addr;
+	struct sockaddr_nl addr = {};
 	socklen_t addr_len = sizeof(addr);
 	int len;