Skip to content

Commit 40d86ef

Browse files
Wait for route RCU callbacks in homa_peer_free_net
homa_peer_free_net releases each route in the namespace with call_rcu(homa_route_free), and homa_route_free dereferences route->key.hnet to find the peertab. But hnet is the pernet data for the namespace, which cleanup_net frees right after the exit methods return (its rcu_barrier comes later). A callback that runs after that reads freed memory. Found by deleting network namespaces that had carried Homa traffic, in a VM: with init_on_free=1 every run oopsed in homa_route_free (6.12 and 7.3); without it, 3 of 8 runs on 7.3 hit a general protection fault there under load. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 4bd0275 commit 40d86ef

2 files changed

Lines changed: 20 additions & 0 deletions

File tree

‎homa_peer.c‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,11 @@ void homa_peer_free_net(struct homa_net *hnet)
172172
WARN(hnet->num_routes != 0, "%s ended up with hnet->num_routes %d",
173173
__func__, hnet->num_routes);
174174
spin_unlock_bh(&peertab->lock);
175+
176+
/* homa_route_free uses hnet, which will be freed as soon as we
177+
* return, so wait for the callbacks queued above.
178+
*/
179+
rcu_barrier();
175180
}
176181

177182
/**

‎test/unit_homa_peer.c‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,21 @@ TEST_F(homa_peer, homa_peer_free_net__basics)
151151
unit_sock_destroy(&hsk2);
152152
}
153153

154+
TEST_F(homa_peer, homa_peer_free_net__wait_for_rcu_callbacks)
155+
{
156+
/* The homa_net is freed as soon as homa_peer_free_net returns, so
157+
* the homa_route_free callbacks (which use it) must have finished.
158+
*/
159+
struct homa_route *route;
160+
161+
route = homa_route_get(&self->hsk, ip1111);
162+
homa_route_release(route);
163+
EXPECT_EQ(1, unit_count_peers(&self->homa));
164+
165+
homa_peer_free_net(self->hnet);
166+
EXPECT_EQ(0, unit_count_peers(&self->homa));
167+
}
168+
154169
TEST_F(homa_peer, homa_route_delete_fn)
155170
{
156171
struct homa_route *route;

0 commit comments

Comments
 (0)