Merge branch 'af_unix-fix-inconsistent-scc_index'

Kuniyuki Iwashima says:

====================
af_unix: Fix inconsistent scc_index.

James Burton reported that a single SCC could have multiple
scc_index and unix_vertex_dead() fails to detect a dead SCC.

Patch 1 fixes it and Patch 2 adds a test case.
====================

Link: https://patch.msgid.link/20260912030852.1467872-1-kuniyu@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2026-09-15 16:45:06 -07:00
commit 433cfc3025
2 changed files with 27 additions and 7 deletions

View File

@ -374,7 +374,7 @@ static bool unix_vertex_dead(struct unix_vertex *vertex)
static LIST_HEAD(unix_visited_vertices);
static unsigned long unix_vertex_grouped_index = UNIX_VERTEX_INDEX_MARK2;
static bool unix_scc_dead(struct list_head *scc, bool fast)
static bool unix_scc_dead(struct list_head *scc)
{
struct unix_vertex *vertex;
bool scc_dead = true;
@ -386,10 +386,6 @@ static bool unix_scc_dead(struct list_head *scc, bool fast)
/* Don't restart DFS from this vertex. */
list_move_tail(&vertex->entry, &unix_visited_vertices);
/* Mark vertex as off-stack for __unix_walk_scc(). */
if (!fast)
vertex->index = unix_vertex_grouped_index;
if (scc_dead)
scc_dead = unix_vertex_dead(vertex);
}
@ -521,6 +517,7 @@ static unsigned long __unix_walk_scc(struct unix_vertex *vertex,
}
if (vertex->index == vertex->scc_index) {
struct unix_vertex *v;
struct list_head scc;
/* SCC finalised.
@ -530,7 +527,13 @@ static unsigned long __unix_walk_scc(struct unix_vertex *vertex,
*/
__list_cut_position(&scc, &vertex_stack, &vertex->scc_entry);
if (unix_scc_dead(&scc, false)) {
list_for_each_entry_reverse(v, &scc, scc_entry) {
/* Mark vertex as off-stack and assign a unique ID. */
v->index = unix_vertex_grouped_index;
v->scc_index = vertex->scc_index;
}
if (unix_scc_dead(&scc)) {
unix_collect_skb(&scc, hitlist);
} else {
if (unix_vertex_max_scc_index < vertex->scc_index)
@ -588,7 +591,7 @@ static void unix_walk_scc_fast(struct sk_buff_head *hitlist)
vertex = list_first_entry(&unix_unvisited_vertices, typeof(*vertex), entry);
list_add(&scc, &vertex->scc_entry);
if (unix_scc_dead(&scc, true)) {
if (unix_scc_dead(&scc)) {
cyclic_sccs--;
unix_collect_skb(&scc, hitlist);
}

View File

@ -378,4 +378,21 @@ TEST_F(scm_rights, backtrack_from_scc)
close_sockets(10);
}
TEST_F(scm_rights, mixed_lowpoint)
{
create_sockets(6);
send_fd(0, 1);
send_fd(1, 2);
send_fd(2, 1);
send_fd(1, 0);
send_fd(3, 4);
send_fd(4, 5);
send_fd(5, 4);
send_fd(4, 3);
close_sockets(6);
}
TEST_HARNESS_MAIN