[COMMIT osv master] netlink: make response message nl_pid equal to 0

8 views
Skip to first unread message

Commit Bot

unread,
Dec 14, 2023, 11:32:43 PM12/14/23
to osv...@googlegroups.com, Waldemar Kozaczuk
From: Waldemar Kozaczuk <jwkoz...@gmail.com>
Committer: Waldemar Kozaczuk <jwkoz...@gmail.com>
Branch: master

netlink: make response message nl_pid equal to 0

Just like Golang, glibc uses netlink interface to implement
functions like getifaddrs() and if_nameindex() behind the hood.
Unlike Golang, glibc validates the netlink responses received
from kernel to have nl_pid = 0 in their headers and ignores them
otherwise and app seems to hang in result.

To fix it, we tweak OSv netlink implementation to initialize
netlink reponse header with zeros. As a result, following unit tests
pass now:

- tst-ifaddrs.cc
- tst-net_if_test.cc
- tst-netlink.cc

Signed-off-by: Waldemar Kozaczuk <jwkoz...@gmail.com>

---
diff --git a/bsd/sys/compat/linux/linux_netlink.cc b/bsd/sys/compat/linux/linux_netlink.cc
--- a/bsd/sys/compat/linux/linux_netlink.cc
+++ b/bsd/sys/compat/linux/linux_netlink.cc
@@ -71,7 +71,7 @@ std::atomic<pid_t> _nl_next_gen_pid(2);

MALLOC_DEFINE(M_NETLINK, "netlink", "netlink socket");

-static struct bsd_sockaddr netlink_src = { 2, PF_NETLINK, };
+static struct bsd_sockaddr_nl netlink_src = { sizeof(bsd_sockaddr_nl), PF_NETLINK, 0, 0, 0};



@@ -293,7 +293,7 @@ netlink_input(struct mbuf *m)

netlink_proto.sp_family = PF_NETLINK;

- raw_input_ext(m, &netlink_proto, &netlink_src, raw_input_netlink_cb);
+ raw_input_ext(m, &netlink_proto, (bsd_sockaddr*)&netlink_src, raw_input_netlink_cb);
}

void
diff --git a/tests/tst-netlink.c b/tests/tst-netlink.c
--- a/tests/tst-netlink.c
+++ b/tests/tst-netlink.c
@@ -97,6 +97,10 @@ int test_netlink(struct nlmsghdr* req, pid_t pid, void (*handle_response)(struct
msg.msg_iov = iov; //Check if we can improve things downstream with some asserts or even error handling
msg.msg_iovlen = 1;

+ memset(&dst_addr, 0, sizeof(dst_addr));
+ msg.msg_name = &dst_addr; //Set msg_name to make kernel return source address
+ msg.msg_namelen = sizeof(dst_addr);
+
memset(buf, 0, BUFSIZE);
msg.msg_iov[0].iov_base = buf;
msg.msg_iov[0].iov_len = BUFSIZE;
@@ -106,6 +110,9 @@ int test_netlink(struct nlmsghdr* req, pid_t pid, void (*handle_response)(struct
die("recvmsg FAILED");
}

+ assert(dst_addr.nl_family == AF_NETLINK);
+ assert(dst_addr.nl_pid == 0); //nl_pid = 0 indicates it came from kernel
+
for (struct nlmsghdr *rsp = (struct nlmsghdr *)buf;
NLMSG_OK(rsp, len); rsp = NLMSG_NEXT(rsp, len))
{
Reply all
Reply to author
Forward
0 new messages