DORMANTno replies

[PATCH iproute] ss: Don't re-print an SCTP listen socket as an assoc

From: Jamie Bainbridge <hidden>
Date: 2026-07-07 06:48:04
Subsystem: the rest · Maintainer: Linus Torvalds

"ss -Sa" prints a LISTEN-state SCTP sock once as a non-assoc when
is_sctp_assoc() correctly returns false, then again when we have cached
the inode in sctp_ino, so is_sctp_assoc() returns true.

On the second pass, we try to print the socket state with
sctp_sstate_name[s->state], but s->state == 10 (SCTP_SS_LISTENING)
but sctp_sstate_name[] only has 8 entries, so we illegally access beyond
the end of the name array.

If you are lucky, the space beyond the array is NULL and the argument to
the print format is printed as "(null)" by the C library:

  $ ./misc/ss -San
  State     Recv-Q Send-Q    Local Address:Port Peer Address:Port
  LISTEN    0      5           192.0.2.10:9001       0.0.0.0:*
  `- (null) 0      5           192.0.2.10:9001       0.0.0.0:*
  `- ESTAB  0      0      192.0.2.10%net1:9001     192.0.2.9:11111

If you are unlucky, the space beyond the array is non-NULL and you
pass an invalid address to the print format:

  $ ./misc/ss -San
  Segmentation fault (core dumped)

The inode is correctly cached at the bottom of inet_show_sock(), so
check if we've already processed this SCTP LISTEN inode and exit early.

  $ ./misc/ss -San
  State    Recv-Q Send-Q    Local Address:Port Peer Address:Port
  LISTEN   0      5           192.0.2.10:9001       0.0.0.0:*
  `- ESTAB 0      0      192.0.2.10%net1:9001     192.0.2.9:11111

We cannot exit later than this (eg: in sock_state_print()) because by
then we're already halfway through a new line in inet_stats_print().

Keep the existing check in is_sctp_assoc() because that is needed to
differentiate related assocs from new endpoints.

Note: there is still a chance of double-printing a listen socket (now
with the correct format if netlink delivers us listen sockets and their
assocs with something else in between:

  $ ./misc/ss -Sane
  State    Recv-Q Send-Q    Local Address:Port Peer Address:Port
LISTEN   0      5           192.0.2.10:9001       0.0.0.0:*     ino:36518
  LISTEN   0      5           192.0.2.10:9002       0.0.0.0:*     ino:44485
  `- ESTAB 0      0      192.0.2.10%net1:9002     192.0.2.9:22222 ino:44485
LISTEN   0      5           192.0.2.10:9001       0.0.0.0:*     ino:36518
  `- ESTAB 0      0      192.0.2.10%net1:9001     122.0.2.9:11111 ino:36518

This behaviour existed before this commit. I don't see a way around this
except to pre-sort the results from netlink which seems unrealistic.

Fixes: f89d46ad63f6f ("ss: Add support for SCTP protocol")
Reported-by: Rustam Kovhaev <redacted>
Signed-off-by: Jamie Bainbridge <redacted>
---
 misc/ss.c | 8 ++++++++
 1 file changed, 8 insertions(+)
diff --git a/misc/ss.c b/misc/ss.c
index 14e9f27a75321556240a5f290b8bcf51c605a4c2..7e94160f7590c35aa187fe00902be8def7593608 100644
--- a/misc/ss.c
+++ b/misc/ss.c
@@ -3764,6 +3764,14 @@ static bool bpf_map_opts_is_enabled(void)
 static int inet_show_sock(struct nlmsghdr *nlh,
 			  struct sockstat *s)
 {
+	/* SCTP assocs share the same inode number with their parent endpoint.
+	 * If we've seen a LISTEN socket inode before, we've already printed it
+	 * and cached the inode at the bottom of this function. We don't want
+	 * to re-print the LISTEN socket again. so exit early.
+	 */
+	if (s->type == IPPROTO_SCTP && s->state == SS_LISTEN && sctp_ino == s->ino)
+		return 0;
+
 	struct rtattr *tb[INET_DIAG_MAX+1];
 	struct inet_diag_msg *r = NLMSG_DATA(nlh);
 	unsigned char v6only = 0;
-- 
2.47.3
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help