Skip to content

Commit 384210c

Browse files
Takamitsu Iwaigregkh
authored andcommitted
net: rose: include node references in rose_neigh refcount
[ Upstream commit da9c9c8 ] Current implementation maintains two separate reference counting mechanisms: the 'count' field in struct rose_neigh tracks references from rose_node structures, while the 'use' field (now refcount_t) tracks references from rose_sock. This patch merges these two reference counting systems using 'use' field for proper reference management. Specifically, this patch adds incrementing and decrementing of rose_neigh->use when rose_neigh->count is incremented or decremented. This patch also modifies rose_rt_free(), rose_rt_device_down() and rose_clear_route() to properly release references to rose_neigh objects before freeing a rose_node through rose_remove_node(). These changes ensure rose_neigh structures are properly freed only when all references, including those from rose_node structures, are released. As a result, this resolves a slab-use-after-free issue reported by Syzbot. Fixes: 1da177e ("Linux-2.6.12-rc2") Reported-by: syzbot+942297eecf7d2d61d1f1@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=942297eecf7d2d61d1f1 Signed-off-by: Takamitsu Iwai <takamitz@amazon.co.jp> Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com> Link: https://patch.msgid.link/20250823085857.47674-4-takamitz@amazon.co.jp Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 203e4f4 commit 384210c

File tree

1 file changed

+16
-2
lines changed

1 file changed

+16
-2
lines changed

net/rose/rose_route.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ static int __must_check rose_add_node(struct rose_route_struct *rose_route,
178178
}
179179
}
180180
rose_neigh->count++;
181+
rose_neigh_hold(rose_neigh);
181182

182183
goto out;
183184
}
@@ -187,6 +188,7 @@ static int __must_check rose_add_node(struct rose_route_struct *rose_route,
187188
rose_node->neighbour[rose_node->count] = rose_neigh;
188189
rose_node->count++;
189190
rose_neigh->count++;
191+
rose_neigh_hold(rose_neigh);
190192
}
191193

192194
out:
@@ -322,6 +324,7 @@ static int rose_del_node(struct rose_route_struct *rose_route,
322324
for (i = 0; i < rose_node->count; i++) {
323325
if (rose_node->neighbour[i] == rose_neigh) {
324326
rose_neigh->count--;
327+
rose_neigh_put(rose_neigh);
325328

326329
if (rose_neigh->count == 0) {
327330
rose_remove_neigh(rose_neigh);
@@ -430,6 +433,7 @@ int rose_add_loopback_node(const rose_address *address)
430433
rose_node_list = rose_node;
431434

432435
rose_loopback_neigh->count++;
436+
rose_neigh_hold(rose_loopback_neigh);
433437

434438
out:
435439
spin_unlock_bh(&rose_node_list_lock);
@@ -461,6 +465,7 @@ void rose_del_loopback_node(const rose_address *address)
461465
rose_remove_node(rose_node);
462466

463467
rose_loopback_neigh->count--;
468+
rose_neigh_put(rose_loopback_neigh);
464469

465470
out:
466471
spin_unlock_bh(&rose_node_list_lock);
@@ -500,6 +505,7 @@ void rose_rt_device_down(struct net_device *dev)
500505
memmove(&t->neighbour[i], &t->neighbour[i + 1],
501506
sizeof(t->neighbour[0]) *
502507
(t->count - i));
508+
rose_neigh_put(s);
503509
}
504510

505511
if (t->count <= 0)
@@ -543,6 +549,7 @@ static int rose_clear_routes(void)
543549
{
544550
struct rose_neigh *s, *rose_neigh;
545551
struct rose_node *t, *rose_node;
552+
int i;
546553

547554
spin_lock_bh(&rose_node_list_lock);
548555
spin_lock_bh(&rose_neigh_list_lock);
@@ -553,8 +560,12 @@ static int rose_clear_routes(void)
553560
while (rose_node != NULL) {
554561
t = rose_node;
555562
rose_node = rose_node->next;
556-
if (!t->loopback)
563+
564+
if (!t->loopback) {
565+
for (i = 0; i < rose_node->count; i++)
566+
rose_neigh_put(t->neighbour[i]);
557567
rose_remove_node(t);
568+
}
558569
}
559570

560571
while (rose_neigh != NULL) {
@@ -1189,7 +1200,7 @@ static int rose_neigh_show(struct seq_file *seq, void *v)
11891200
(rose_neigh->loopback) ? "RSLOOP-0" : ax2asc(buf, &rose_neigh->callsign),
11901201
rose_neigh->dev ? rose_neigh->dev->name : "???",
11911202
rose_neigh->count,
1192-
refcount_read(&rose_neigh->use) - 1,
1203+
refcount_read(&rose_neigh->use) - rose_neigh->count - 1,
11931204
(rose_neigh->dce_mode) ? "DCE" : "DTE",
11941205
(rose_neigh->restarted) ? "yes" : "no",
11951206
ax25_display_timer(&rose_neigh->t0timer) / HZ,
@@ -1294,6 +1305,7 @@ void __exit rose_rt_free(void)
12941305
struct rose_neigh *s, *rose_neigh = rose_neigh_list;
12951306
struct rose_node *t, *rose_node = rose_node_list;
12961307
struct rose_route *u, *rose_route = rose_route_list;
1308+
int i;
12971309

12981310
while (rose_neigh != NULL) {
12991311
s = rose_neigh;
@@ -1307,6 +1319,8 @@ void __exit rose_rt_free(void)
13071319
t = rose_node;
13081320
rose_node = rose_node->next;
13091321

1322+
for (i = 0; i < t->count; i++)
1323+
rose_neigh_put(t->neighbour[i]);
13101324
rose_remove_node(t);
13111325
}
13121326

0 commit comments

Comments
 (0)