From: Siddharth Chintamaneni <sidchintamaneni@gmail.com>
To: Kuniyuki Iwashima <kuniyu@google.com>,
Eric Dumazet <edumazet@kernel.org>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>
Cc: Simon Horman <horms@kernel.org>, Shuah Khan <shuah@kernel.org>,
Willem de Bruijn <willemb@google.com>,
Jann Horn <jannh@google.com>, Kirill Tkhai <tkhai@ya.ru>,
apais@microsoft.com, rlmenge@gmail.com,
hargar@linux.microsoft.com, netdev@vger.kernel.org,
linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org,
Siddharth Chintamaneni <sidchintamaneni@gmail.com>
Subject: [PATCH net 4/4] selftest: af_unix: Test SIOCINQ and scm_fds with OOB and dgram disconnect.
Date: Fri, 6 Nov 2026 05:19:05 +0000 [thread overview]
Message-ID: <20261106051905.218638-5-sidchintamaneni@gmail.com> (raw)
In-Reply-To: <20261106051905.218638-1-sidchintamaneni@gmail.com>
Verify in msg_oob's __resetpair() that ioctl(SIOCINQ) reports 0 unread
bytes after draining the stream receive queue, and add oob_fdinfo and
dgram_disconnect_fdinfo tests in scm_rights.c verifying that
/proc/self/fdinfo/<fd> (scm_fds) returns to 0 when OOB skbs carrying
SCM_RIGHTS are skipped or freed and when a dgram socket disconnects with
queued SCM_RIGHTS skbs.
Signed-off-by: Siddharth Chintamaneni <sidchintamaneni@gmail.com>
---
tools/testing/selftests/net/af_unix/msg_oob.c | 12 +-
.../selftests/net/af_unix/scm_rights.c | 108 ++++++++++++++++++
2 files changed, 119 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/net/af_unix/msg_oob.c b/tools/testing/selftests/net/af_unix/msg_oob.c
index f051d79f7a8e..7d5a25485048 100644
--- a/tools/testing/selftests/net/af_unix/msg_oob.c
+++ b/tools/testing/selftests/net/af_unix/msg_oob.c
@@ -5,6 +5,7 @@
#include <string.h>
#include <unistd.h>
+#include <linux/sockios.h>
#include <netinet/in.h>
#include <sys/epoll.h>
#include <sys/ioctl.h>
@@ -336,8 +337,17 @@ static void __resetpair(struct __test_metadata *_metadata,
{
int i;
- for (i = 0; i < 2; i++)
+ for (i = 0; i < 2; i++) {
+ if (!reset) {
+ int inq, ret;
+
+ ret = ioctl(self->fd[i * 2 + 1], SIOCINQ, &inq);
+ ASSERT_EQ(ret, 0);
+ ASSERT_EQ(inq, 0);
+ }
+
close(self->fd[i * 2 + 1]);
+ }
__recvpair(_metadata, self, "", reset ? -ECONNRESET : 0, 1,
variant->peek ? MSG_PEEK : 0, true);
diff --git a/tools/testing/selftests/net/af_unix/scm_rights.c b/tools/testing/selftests/net/af_unix/scm_rights.c
index c165f250220a..38a125d9f6e4 100644
--- a/tools/testing/selftests/net/af_unix/scm_rights.c
+++ b/tools/testing/selftests/net/af_unix/scm_rights.c
@@ -378,6 +378,36 @@ TEST_F(scm_rights, backtrack_from_scc)
close_sockets(10);
}
+static int count_scm_fds(struct __test_metadata *_metadata, int fd)
+{
+ char path[64], *line = NULL;
+ int scm_fds = -1, ret;
+ size_t unused;
+ FILE *f;
+
+ snprintf(path, sizeof(path), "/proc/self/fdinfo/%d", fd);
+
+ f = fopen(path, "r");
+ ASSERT_NE(NULL, f);
+
+ while (getline(&line, &unused, f) != -1) {
+ if (strncmp(line, "scm_fds:", 8))
+ continue;
+
+ ret = sscanf(line + 8, "%d", &scm_fds);
+ ASSERT_EQ(1, ret);
+
+ break;
+ }
+
+ free(line);
+
+ ret = fclose(f);
+ ASSERT_EQ(0, ret);
+
+ return scm_fds;
+}
+
TEST_F(scm_rights, mixed_lowpoint)
{
create_sockets(6);
@@ -395,4 +425,82 @@ TEST_F(scm_rights, mixed_lowpoint)
close_sockets(6);
}
+TEST_F(scm_rights, oob_fdinfo)
+{
+ int recv_fd, ret;
+ char buf[2];
+
+ if (!(variant->flags & MSG_OOB) || variant->disabled)
+ return;
+
+ create_sockets(2);
+
+ if (variant->test_listener) {
+ recv_fd = accept(self->fd[0], NULL, NULL);
+ ASSERT_LE(0, recv_fd);
+ } else {
+ recv_fd = self->fd[0];
+ }
+
+ /* 1. Unconsumed OOB skb skipped by normal recv() in manage_oob() */
+ send_fd(0, 0);
+ ASSERT_EQ(2, count_scm_fds(_metadata, recv_fd));
+ ret = send(self->fd[1], "a", 1, 0);
+ ASSERT_EQ(1, ret);
+ ret = recv(recv_fd, buf, 1, 0);
+ ASSERT_EQ(1, ret);
+ ASSERT_EQ(0, count_scm_fds(_metadata, recv_fd));
+
+ /* 2. Consumed OOB skb freed by normal recv() in manage_oob() */
+ send_fd(0, 0);
+ ASSERT_EQ(2, count_scm_fds(_metadata, recv_fd));
+ ret = recv(recv_fd, buf, 1, MSG_OOB);
+ ASSERT_EQ(1, ret);
+ ret = send(self->fd[1], "a", 1, 0);
+ ASSERT_EQ(1, ret);
+ ret = recv(recv_fd, buf, 1, 0);
+ ASSERT_EQ(1, ret);
+ ASSERT_EQ(0, count_scm_fds(_metadata, recv_fd));
+
+ /* 3. Consumed OOB skb freed by consecutive recv(MSG_OOB) */
+ send_fd(0, 0);
+ ASSERT_EQ(2, count_scm_fds(_metadata, recv_fd));
+ ret = recv(recv_fd, buf, 1, MSG_OOB);
+ ASSERT_EQ(1, ret);
+ ret = send(self->fd[1], "y", 1, MSG_OOB);
+ ASSERT_EQ(1, ret);
+ ret = recv(recv_fd, buf, 1, MSG_OOB);
+ ASSERT_EQ(1, ret);
+ ASSERT_EQ(0, count_scm_fds(_metadata, recv_fd));
+
+ if (variant->test_listener) {
+ ret = close(recv_fd);
+ ASSERT_EQ(0, ret);
+ }
+
+ close_sockets(2);
+}
+
+TEST_F(scm_rights, dgram_disconnect_fdinfo)
+{
+ struct sockaddr addr = {
+ .sa_family = AF_UNSPEC,
+ };
+ int ret;
+
+ if (variant->type != SOCK_DGRAM || variant->disabled)
+ return;
+
+ create_sockets(2);
+
+ send_fd(0, 0);
+ ASSERT_EQ(2, count_scm_fds(_metadata, self->fd[0]));
+
+ ret = connect(self->fd[0], &addr, sizeof(addr.sa_family));
+ ASSERT_EQ(0, ret);
+ ASSERT_EQ(0, count_scm_fds(_metadata, self->fd[0]));
+
+ close_sockets(2);
+}
+
TEST_HARNESS_MAIN
--
2.43.0
next prev parent reply other threads:[~2026-11-06 5:19 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-06 5:19 [PATCH net 0/4] af_unix: Fix inq_len and scm_stat.nr_fds accounting leaks Siddharth Chintamaneni
2026-11-06 5:19 ` [PATCH net 1/4] af_unix: Fix inq_len leak when skipping unread OOB skb Siddharth Chintamaneni
2026-11-06 5:19 ` [PATCH net 2/4] af_unix: Fix scm_stat.nr_fds leaks for " Siddharth Chintamaneni
2026-11-10 6:38 ` netdev-bot+sashiko
2026-11-06 5:19 ` [PATCH net 3/4] af_unix: Fix scm_stat.nr_fds leak in unix_dgram_disconnected() Siddharth Chintamaneni
2026-11-10 6:38 ` netdev-bot+sashiko
2026-11-06 5:19 ` Siddharth Chintamaneni [this message]
2026-11-10 6:38 ` [PATCH net 4/4] selftest: af_unix: Test SIOCINQ and scm_fds with OOB and dgram disconnect netdev-bot+sashiko
2026-11-06 5:21 ` [PATCH net 0/4] af_unix: Fix inq_len and scm_stat.nr_fds accounting leaks netdev-bot+sinfo
2026-11-10 6:38 ` Kuniyuki Iwashima
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=20261106051905.218638-5-sidchintamaneni@gmail.com \
--to=sidchintamaneni@gmail.com \
--cc=apais@microsoft.com \
--cc=edumazet@kernel.org \
--cc=hargar@linux.microsoft.com \
--cc=horms@kernel.org \
--cc=jannh@google.com \
--cc=kuba@kernel.org \
--cc=kuniyu@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=rlmenge@gmail.com \
--cc=shuah@kernel.org \
--cc=tkhai@ya.ru \
--cc=willemb@google.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.