* [PATCH iproute2 v2 0/2] ss: fix vsock port filtering
@ 2026-08-17 12:54 Luigi Leonardi
2026-08-17 12:54 ` [PATCH iproute2 v2 1/2] ss: move lport and rport in struct sockstat from int to long Luigi Leonardi
2026-08-17 12:54 ` [PATCH iproute2 v2 2/2] ss: fix vsock port filter Luigi Leonardi
0 siblings, 2 replies; 3+ messages in thread
From: Luigi Leonardi @ 2026-08-17 12:54 UTC (permalink / raw)
To: Stefano Garzarella, Stefan Hajnoczi, netdev, Luigi Leonardi
Cc: Stephen Hemminger
Vsock port filtering is broken for ports in [1, 2^31−1] (i.e. any port
whose u32 representation has bit 31 clear, which includes all ordinarily
assigned vsock ports).
To reproduce:
ncat -l --vsock -p 27354
ss --vsock -l src :27354 # shows nothing
# Without the filter the socket is visible:
ss --vsock -l
Ports in [2^31, UINT_MAX−1] are not affected by accident.
aafilter.port was extended to 8 bytes to support unix socket inode
numbers larger than INT_MAX (see 012cb515). The vsock parsing path
initialises a.port to -1L and then calls get_u32() via a cast to write
the user-supplied port into it. get_u32() only writes 4 bytes, leaving
the upper 32 bits as 0xFFFFFFFF. For ports < 2^31 this produces a
mismatch with sockstat.lport.
For ports >= 2^31 the int-to-long sign extension also fills
the upper 32 bits with 0xFFFFFFFF, accidentally matching the corrupted
a.port and hiding the bug.
Commit 1 switches from int to long for sockstat.lport/rport
Commit 2 fixes a bug in the parsing of the filter port, that didn't
clear the upper bits.
Signed-off-by: Luigi Leonardi <leonardi@redhat.com>
---
Changes in v2:
- Expanded lport and rport in sockstat from int to long [Stefano]
- Applied suggestion from Stephen for port filtering.
- Link to v1: https://lore.kernel.org/all/20260421-fix_vsock-v1-1-812c80a76c1a@redhat.com
---
Luigi Leonardi (2):
ss: move lport and rport in struct sockstat from int to long
ss: fix vsock port filter
misc/ss.c | 30 +++++++++++++++++-------------
1 file changed, 17 insertions(+), 13 deletions(-)
---
base-commit: da2ccdf862cb1eab45de082cc71fcb4e5d712e78
change-id: 20260817-fix_vsock-f7b374d5cadd
Best regards,
--
Luigi Leonardi <leonardi@redhat.com>
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH iproute2 v2 1/2] ss: move lport and rport in struct sockstat from int to long
2026-08-17 12:54 [PATCH iproute2 v2 0/2] ss: fix vsock port filtering Luigi Leonardi
@ 2026-08-17 12:54 ` Luigi Leonardi
2026-08-17 12:54 ` [PATCH iproute2 v2 2/2] ss: fix vsock port filter Luigi Leonardi
1 sibling, 0 replies; 3+ messages in thread
From: Luigi Leonardi @ 2026-08-17 12:54 UTC (permalink / raw)
To: Stefano Garzarella, Stefan Hajnoczi, netdev, Luigi Leonardi
Commit 012cb515 ("ss: change aafilter port from int to long (inode
support)") widened aafilter.port to long so that unix socket inode
numbers larger than INT_MAX can be used as port filter values, but left
sockstat.lport and sockstat.rport as int. This means large u32 values
(e.g. vsock ports or unix inodes > INT_MAX) are truncated on the
socket-stat side, making the comparison against aafilter.port always
fail.
Widen lport and rport to long and update the sscanf format specifiers
in proc_parse_inet_addr() and unix_show() accordingly.
Fixes: 012cb515 ("ss: change aafilter port from int to long (inode support)")
Suggested-by: Stefano Garzarella <sgarzare@redhat.com>
Signed-off-by: Luigi Leonardi <leonardi@redhat.com>
---
misc/ss.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/misc/ss.c b/misc/ss.c
index 14e9f27a..ff1a88de 100644
--- a/misc/ss.c
+++ b/misc/ss.c
@@ -809,8 +809,8 @@ struct sockstat {
uint16_t raw_prot;
inet_prefix local;
inet_prefix remote;
- int lport;
- int rport;
+ long lport;
+ long rport;
int state;
int rq, wq;
unsigned int ino;
@@ -2490,23 +2490,23 @@ static int proc_parse_inet_addr(char *loc, char *rem, int family, struct
{
s->local.family = s->remote.family = family;
if (family == AF_INET) {
- sscanf(loc, "%x:%x", s->local.data, (unsigned *)&s->lport);
- sscanf(rem, "%x:%x", s->remote.data, (unsigned *)&s->rport);
+ sscanf(loc, "%x:%lx", s->local.data, (unsigned long *)&s->lport);
+ sscanf(rem, "%x:%lx", s->remote.data, (unsigned long *)&s->rport);
s->local.bytelen = s->remote.bytelen = 4;
return 0;
} else {
- sscanf(loc, "%08x%08x%08x%08x:%x",
+ sscanf(loc, "%08x%08x%08x%08x:%lx",
s->local.data,
s->local.data + 1,
s->local.data + 2,
s->local.data + 3,
- &s->lport);
- sscanf(rem, "%08x%08x%08x%08x:%x",
+ (unsigned long *)&s->lport);
+ sscanf(rem, "%08x%08x%08x%08x:%lx",
s->remote.data,
s->remote.data + 1,
s->remote.data + 2,
s->remote.data + 3,
- &s->rport);
+ (unsigned long *)&s->rport);
s->local.bytelen = s->remote.bytelen = 16;
return 0;
}
@@ -4638,8 +4638,8 @@ static int unix_show(struct filter *f)
if (!(u = calloc(1, sizeof(*u))))
break;
- if (sscanf(buf, "%x: %x %x %x %x %x %d %s",
- &u->rport, &u->rq, &u->wq, &flags, &u->type,
+ if (sscanf(buf, "%lx: %x %x %x %x %x %d %s",
+ (unsigned long *)&u->rport, &u->rq, &u->wq, &flags, &u->type,
&u->state, &u->ino, name) < 8)
name[0] = 0;
--
2.55.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH iproute2 v2 2/2] ss: fix vsock port filter
2026-08-17 12:54 [PATCH iproute2 v2 0/2] ss: fix vsock port filtering Luigi Leonardi
2026-08-17 12:54 ` [PATCH iproute2 v2 1/2] ss: move lport and rport in struct sockstat from int to long Luigi Leonardi
@ 2026-08-17 12:54 ` Luigi Leonardi
1 sibling, 0 replies; 3+ messages in thread
From: Luigi Leonardi @ 2026-08-17 12:54 UTC (permalink / raw)
To: Stefano Garzarella, Stefan Hajnoczi, netdev, Luigi Leonardi
Cc: Stephen Hemminger
parse_hostcond() initializes aafilter.port to -1L (0xFFFFFFFFFFFFFFFF)
as a sentinel for "no port filter". When parsing a vsock port it called
get_u32() via a cast:
get_u32((__u32 *)&a.port, port, 0)
get_u32() only writes 4 bytes, leaving the upper 32 bits of the 8-byte
long set from the -1 initialization. For example, for port 27354 this
produces 0xFFFFFFFF00006ADA, which never compares equal to sockstat.lport and
causes all vsock port filters to silently match nothing.
Fix by parsing into a temporary __u32 and assigning it to a.port, which
zero-extends the value correctly. When the user specifies '*' the if
block is skipped entirely and the -1 sentinel is preserved.
Fixes: 012cb515 ("ss: change aafilter port from int to long (inode support)")
Suggested-by: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: Luigi Leonardi <leonardi@redhat.com>
---
misc/ss.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/misc/ss.c b/misc/ss.c
index ff1a88de..a3570715 100644
--- a/misc/ss.c
+++ b/misc/ss.c
@@ -2322,9 +2322,13 @@ void *parse_hostcond(char *addr, bool is_port)
port = find_port(addr, is_port);
- if (port && strcmp(port, "*") &&
- get_u32((__u32 *)&a.port, port, 0))
- return NULL;
+ if (port && strcmp(port, "*")) {
+ __u32 vport;
+
+ if (get_u32(&vport, port, 0))
+ return NULL;
+ a.port = vport;
+ }
if (!is_port && addr[0] && strcmp(addr, "*")) {
a.addr.bitlen = 32;
--
2.55.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-08-17 12:54 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-17 12:54 [PATCH iproute2 v2 0/2] ss: fix vsock port filtering Luigi Leonardi
2026-08-17 12:54 ` [PATCH iproute2 v2 1/2] ss: move lport and rport in struct sockstat from int to long Luigi Leonardi
2026-08-17 12:54 ` [PATCH iproute2 v2 2/2] ss: fix vsock port filter Luigi Leonardi
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.