mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH net] tipc: don't count unjoined publications as receivers
@ 2026-11-07  8:24 shaos
  2026-11-07  8:31 ` netdev-bot+sinfo
  0 siblings, 1 reply; 2+ messages in thread
From: shaos @ 2026-11-07  8:24 UTC (permalink / raw)
  To: jmaloy
  Cc: Tung Quang Nguyen, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Simon Horman, netdev, tipc-discussion, linux-kernel

Hello,

A local process with no capabilities can block sends from a TIPC
communication group by publishing the matching service range from a
socket that never joins the group. I reproduced it with a root sender
and a separate unprivileged group member on the same node. A third,
unprivileged process binds the same type and instance as an ordinary
TIPC service. The sender's first nonblocking send returns -EAGAIN. Its
subsequent blocking send remains asleep; after 12 seconds,
poll(POLLOUT) is still clear.

The publisher has CapEff=0 and NoNewPrivs=1. It does not need
CAP_NET_ADMIN or CAP_NET_RAW. The guest init enables the TIPC bearer
before dropping privileges. The test uses one local node; I have not
tested a remote-node trigger. This demonstrates a local availability
issue for the group service only. There is no memory corruption,
information disclosure, or privilege escalation.

tipc_nametbl_build_group() and TIPC_PUBLISHED events create
MBR_PUBLISHED entries for matching service publications.
tipc_group_is_receiver() currently accepts this state. Its
zero-initialized window is added to small_win, so
tipc_group_bc_cong() blocks a sender indefinitely when the ordinary
socket does not complete the group JOIN handshake. A real group
member is present in the reproducer, so this is not an empty-group
send.

This is distinct from the group broadcast hang caused by deleting
the last unacked member: this trigger needs no ACK loss or member
departure and occurs before the first broadcast.

HEAD: commit c03c1a14507dfaf8b856c2608f9ac216021fc222 ("Linux 7.3")
git tree:       upstream Linux, local branch master
source version: Linux 7.3.0 (v7.3)
compiler:       gcc 11.4.0, GNU ld 2.38
QEMU:           6.2.0

Raw reproduction files:

console-output.txt
https://gist.githubusercontent.com/shaos26/243e46a190cef51fbe6a1e8cf1bcdede/raw/1cb4d487be1eace60d6d68ab384f85057b296b41/console-output.txt
patched-console-output.txt
https://gist.githubusercontent.com/shaos26/243e46a190cef51fbe6a1e8cf1bcdede/raw/1cb4d487be1eace60d6d68ab384f85057b296b41/patched-console-output.txt
kernel-config.txt
https://gist.githubusercontent.com/shaos26/243e46a190cef51fbe6a1e8cf1bcdede/raw/1cb4d487be1eace60d6d68ab384f85057b296b41/kernel-config.txt
poc.c
https://gist.githubusercontent.com/shaos26/243e46a190cef51fbe6a1e8cf1bcdede/raw/1cb4d487be1eace60d6d68ab384f85057b296b41/poc.c
init
https://gist.githubusercontent.com/shaos26/243e46a190cef51fbe6a1e8cf1bcdede/raw/1cb4d487be1eace60d6d68ab384f85057b296b41/init
build-initramfs.sh
https://gist.githubusercontent.com/shaos26/243e46a190cef51fbe6a1e8cf1bcdede/raw/1cb4d487be1eace60d6d68ab384f85057b296b41/build-initramfs.sh
run-qemu.sh
https://gist.githubusercontent.com/shaos26/243e46a190cef51fbe6a1e8cf1bcdede/raw/1cb4d487be1eace60d6d68ab384f85057b296b41/run-qemu.sh

With these files saved in a Linux tree at the HEAD above:

    cp kernel-config.txt .config
    make olddefconfig
    make -j"$(nproc)" bzImage
    ./build-initramfs.sh
    ./run-qemu.sh arch/x86/boot/bzImage phantom-group

The unmodified kernel reproduced:

    POLL_BEFORE_FIRST_SEND=4
    NONBLOCK_FIRST_SEND ret=-1 errno=11
    POC_RESULT POSITIVE_SEND_BLOCKED observe_ms=12000 pollout=0

The patched kernel was built from the same HEAD and config. The same
test reported:

    POLL_BEFORE_FIRST_SEND=4
    NONBLOCK_FIRST_SEND ret=1 errno=0
    POC_RESULT CONTROL_SEND_RETURNED ret=1 errno=0

The patched run also preserves POLLOUT for a legitimate group member.
The patch passed checkpatch.pl --no-tree --strict and git apply --check;
the patched kernel and static PoC both built successfully.

Exclude MBR_PUBLISHED entries from receiver accounting. When the JOIN
handshake changes a member to MBR_JOINED, open the group even if that
member was not on the small-window list.

Fixes: b7d42635517f ("tipc: introduce flow control for group broadcast messages")
Signed-off-by: shaos <shawnq1@163.com>
---
diff --git a/net/tipc/group.c b/net/tipc/group.c
index 74f6d3dac0784..61fc57d96f365 100644
--- a/net/tipc/group.c
+++ b/net/tipc/group.c
@@ -105,9 +105,12 @@ static void tipc_group_proto_xmit(struct tipc_group *grp, struct tipc_member *m,
 static void tipc_group_open(struct tipc_member *m, bool *wakeup)
 {
 	*wakeup = false;
-	if (list_empty(&m->small_win))
-		return;
-	list_del_init(&m->small_win);
+	if (list_empty(&m->small_win)) {
+		if (m->state != MBR_JOINED || *m->group->open)
+			return;
+	} else {
+		list_del_init(&m->small_win);
+	}
 	*m->group->open = true;
 	*wakeup = true;
 }
@@ -145,7 +148,8 @@ u16 tipc_group_bc_snd_nxt(struct tipc_group *grp)
 
 static bool tipc_group_is_receiver(struct tipc_member *m)
 {
-	return m && m->state != MBR_JOINING && m->state != MBR_LEAVING;
+	return m && m->state != MBR_JOINING && m->state != MBR_PUBLISHED &&
+	       m->state != MBR_LEAVING;
 }
 
 static bool tipc_group_is_sender(struct tipc_member *m)


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-11-07  8:31 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-07  8:24 [PATCH net] tipc: don't count unjoined publications as receivers shaos
2026-11-07  8:31 ` netdev-bot+sinfo

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®