From: Jhonata Poma-Hansen via B4 Relay <devnull+jhonata.poma.gmail.com@kernel.org>
To: "David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@kernel.org>,
Jakub Kicinski <kuba@kernel.org>,
Paolo Abeni <pabeni@redhat.com>, Simon Horman <horms@kernel.org>,
Shuah Khan <shuah@kernel.org>
Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-kselftest@vger.kernel.org,
Kuniyuki Iwashima <kuniyu@google.com>,
Marek Szyprowski <m.szyprowski@samsung.com>,
Jhonata Poma-Hansen <jhonata.poma@gmail.com>
Subject: [PATCH net v2 2/2] selftests: net: netlink-dumps: start a dump with a notification queued
Date: Tue, 27 Oct 2026 15:04:02 +0100 [thread overview]
Message-ID: <20261027-netlink-dump-livelock-v2-2-c4bb05352a33@gmail.com> (raw)
In-Reply-To: <20261027-netlink-dump-livelock-v2-0-c4bb05352a33@gmail.com>
From: Jhonata Poma-Hansen <jhonata.poma@gmail.com>
Add a test which starts a link dump on a socket with SO_RCVBUF 2048
while a link notification is still queued, after a large read made the
kernel attempt large dump skbs. It reads like libnl does, peeking
before each read, and expects the dump to complete with a zero status
and at least one link. The notifications come from bringing lo up and
down, so the test runs in its own netns and is skipped without the
privileges to create one.
The test fails without the previous patch.
Signed-off-by: Jhonata Poma-Hansen <jhonata.poma@gmail.com>
---
tools/testing/selftests/net/netlink-dumps.c | 102 ++++++++++++++++++++++++++++
1 file changed, 102 insertions(+)
diff --git a/tools/testing/selftests/net/netlink-dumps.c b/tools/testing/selftests/net/netlink-dumps.c
index 51129c564..4a94a2516 100644
--- a/tools/testing/selftests/net/netlink-dumps.c
+++ b/tools/testing/selftests/net/netlink-dumps.c
@@ -2,9 +2,12 @@
#define _GNU_SOURCE
+#include <errno.h>
#include <fcntl.h>
+#include <sched.h>
#include <stdio.h>
#include <string.h>
+#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/syscall.h>
@@ -260,4 +263,103 @@ TEST(close_with_ref)
usleep(100 * 1000);
}
+static int lo_set_up(int sock, bool up)
+{
+ struct ifreq ifr = {};
+
+ strcpy(ifr.ifr_name, "lo");
+ if (ioctl(sock, SIOCGIFFLAGS, &ifr))
+ return -1;
+ if (up)
+ ifr.ifr_flags |= IFF_UP;
+ else
+ ifr.ifr_flags &= ~IFF_UP;
+ return ioctl(sock, SIOCSIFFLAGS, &ifr);
+}
+
+static const struct {
+ struct nlmsghdr nlhdr;
+ struct ifinfomsg ifm;
+} dump_links = {
+ .nlhdr = {
+ .nlmsg_len = sizeof(dump_links),
+ .nlmsg_type = RTM_GETLINK,
+ .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP,
+ .nlmsg_seq = 1,
+ },
+ .ifm = {
+ .ifi_family = AF_UNSPEC,
+ },
+};
+
+// A dump started while a notification is still queued must make progress
+// for a reader which peeks before reading, like libnl does
+TEST(dump_with_queued_ntf)
+{
+ struct sockaddr_nl addr = {
+ .nl_family = AF_NETLINK,
+ .nl_groups = RTMGRP_LINK,
+ };
+ int netlink_sock, inet_sock, i, ret, links = 0;
+ int rcvbuf = 2048;
+ bool done = false;
+ char buf[32768];
+ ssize_t n;
+
+ ret = unshare(CLONE_NEWNET);
+ if (ret && errno == EPERM)
+ SKIP(return, "Needs CAP_SYS_ADMIN for a netns");
+ ASSERT_EQ(ret, 0);
+
+ inet_sock = socket(AF_INET, SOCK_DGRAM, 0);
+ ASSERT_GE(inet_sock, 0);
+ netlink_sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ ASSERT_GE(netlink_sock, 0);
+ ASSERT_EQ(setsockopt(netlink_sock, SOL_SOCKET, SO_RCVBUF,
+ &rcvbuf, sizeof(rcvbuf)), 0);
+ ASSERT_EQ(bind(netlink_sock, (struct sockaddr *)&addr,
+ sizeof(addr)), 0);
+
+ // A large read makes the kernel attempt large dump skbs
+ ASSERT_EQ(lo_set_up(inet_sock, true), 0);
+ n = recv(netlink_sock, buf, sizeof(buf), 0);
+ ASSERT_GE(n, (ssize_t)sizeof(struct nlmsghdr));
+
+ // Leave one notification queued, then start the dump
+ ASSERT_EQ(lo_set_up(inet_sock, false), 0);
+ n = send(netlink_sock, &dump_links, sizeof(dump_links), 0);
+ ASSERT_EQ(n, sizeof(dump_links));
+
+ for (i = 0; i < 100 && !done; i++) {
+ struct nlmsghdr *nlh;
+
+ n = recv(netlink_sock, buf, sizeof(buf),
+ MSG_PEEK | MSG_TRUNC | MSG_DONTWAIT);
+ if (n < 0)
+ continue;
+ n = recv(netlink_sock, buf, sizeof(buf), MSG_DONTWAIT);
+ if (n < 0)
+ continue;
+
+ for (nlh = (struct nlmsghdr *)buf; NLMSG_OK(nlh, n);
+ nlh = NLMSG_NEXT(nlh, n)) {
+ if (nlh->nlmsg_seq != dump_links.nlhdr.nlmsg_seq)
+ continue;
+ if (nlh->nlmsg_type == NLMSG_ERROR)
+ EXPECT_EQ(*(int *)NLMSG_DATA(nlh), 0);
+ if (nlh->nlmsg_type == RTM_NEWLINK)
+ links++;
+ if (nlh->nlmsg_type == NLMSG_DONE) {
+ EXPECT_EQ(*(int *)NLMSG_DATA(nlh), 0);
+ done = true;
+ }
+ }
+ }
+ EXPECT_TRUE(done);
+ EXPECT_GE(links, 1);
+
+ close(netlink_sock);
+ close(inet_sock);
+}
+
TEST_HARNESS_MAIN
--
2.54.0
prev parent reply other threads:[~2026-10-27 14:04 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-27 14:04 [PATCH net v2 0/2] netlink: fix a dump livelock " Jhonata Poma-Hansen via B4 Relay
2026-10-27 14:04 ` [PATCH net v2 1/2] netlink: check sk_rcvbuf before charging the dump skb Jhonata Poma-Hansen via B4 Relay
2026-10-27 16:17 ` Eric Dumazet
2026-10-27 14:04 ` Jhonata Poma-Hansen via B4 Relay [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261027-netlink-dump-livelock-v2-2-c4bb05352a33@gmail.com \
--to=devnull+jhonata.poma.gmail.com@kernel.org \
--cc=davem@davemloft.net \
--cc=edumazet@kernel.org \
--cc=horms@kernel.org \
--cc=jhonata.poma@gmail.com \
--cc=kuba@kernel.org \
--cc=kuniyu@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=m.szyprowski@samsung.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=shuah@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®