Message ID | 7935e3668947d91c69a00a3b3db7489d5d2a4325.1511195030.git.sowmini.varadhan@oracle.com |
---|---|
State | Accepted, archived |
Delegated to: | David Miller |
Headers | show |
Series | rds-tcp netns delete related fixes | expand |
On 11/30/2017 11:11 AM, Sowmini Varadhan wrote: > The rds_tcp_kill_sock() function parses the rds_tcp_conn_list > to find the rds_connection entries marked for deletion as part > of the netns deletion under the protection of the rds_tcp_conn_lock. > Since the rds_tcp_conn_list tracks rds_tcp_connections (which > have a 1:1 mapping with rds_conn_path), multiple tc entries in > the rds_tcp_conn_list will map to a single rds_connection, and will > be deleted as part of the rds_conn_destroy() operation that is > done outside the rds_tcp_conn_lock. > > The rds_tcp_conn_list traversal done under the protection of > rds_tcp_conn_lock should not leave any doomed tc entries in > the list after the rds_tcp_conn_lock is released, else another > concurrently executiong netns delete (for a differnt netns) thread > may trip on these entries. > > Reported-by: syzbot <syzkaller@googlegroups.com> > Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com> > --- Acked-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
diff --git a/net/rds/tcp.c b/net/rds/tcp.c index f580f72..39f502d 100644 --- a/net/rds/tcp.c +++ b/net/rds/tcp.c @@ -306,7 +306,8 @@ static void rds_tcp_conn_free(void *arg) rdsdebug("freeing tc %p\n", tc); spin_lock_irqsave(&rds_tcp_conn_lock, flags); - list_del(&tc->t_tcp_node); + if (!tc->t_tcp_node_detached) + list_del(&tc->t_tcp_node); spin_unlock_irqrestore(&rds_tcp_conn_lock, flags); kmem_cache_free(rds_tcp_conn_slab, tc); @@ -510,8 +511,12 @@ static void rds_tcp_kill_sock(struct net *net) if (net != c_net || !tc->t_sock) continue; - if (!list_has_conn(&tmp_list, tc->t_cpath->cp_conn)) + if (!list_has_conn(&tmp_list, tc->t_cpath->cp_conn)) { list_move_tail(&tc->t_tcp_node, &tmp_list); + } else { + list_del(&tc->t_tcp_node); + tc->t_tcp_node_detached = true; + } } spin_unlock_irq(&rds_tcp_conn_lock); list_for_each_entry_safe(tc, _tc, &tmp_list, t_tcp_node) diff --git a/net/rds/tcp.h b/net/rds/tcp.h index f8800b7..8775349 100644 --- a/net/rds/tcp.h +++ b/net/rds/tcp.h @@ -11,6 +11,7 @@ struct rds_tcp_incoming { struct rds_tcp_connection { struct list_head t_tcp_node; + bool t_tcp_node_detached; struct rds_conn_path *t_cpath; /* t_conn_path_lock synchronizes the connection establishment between * rds_tcp_accept_one and rds_tcp_conn_path_connect
The rds_tcp_kill_sock() function parses the rds_tcp_conn_list to find the rds_connection entries marked for deletion as part of the netns deletion under the protection of the rds_tcp_conn_lock. Since the rds_tcp_conn_list tracks rds_tcp_connections (which have a 1:1 mapping with rds_conn_path), multiple tc entries in the rds_tcp_conn_list will map to a single rds_connection, and will be deleted as part of the rds_conn_destroy() operation that is done outside the rds_tcp_conn_lock. The rds_tcp_conn_list traversal done under the protection of rds_tcp_conn_lock should not leave any doomed tc entries in the list after the rds_tcp_conn_lock is released, else another concurrently executiong netns delete (for a differnt netns) thread may trip on these entries. Reported-by: syzbot <syzkaller@googlegroups.com> Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com> --- net/rds/tcp.c | 9 +++++++-- net/rds/tcp.h | 1 + 2 files changed, 8 insertions(+), 2 deletions(-)