aboutsummaryrefslogtreecommitdiff
path: root/net/sctp
diff options
context:
space:
mode:
authorXin Long2016-01-22 01:49:08 +0800
committerDavid S. Miller2016-01-28 15:59:32 -0800
commitfba4c330c5b9d1beeae08a42ed4430f5055e7f27 (patch)
tree22a304daa8d4cb74a609587a841e3f85a7b57348 /net/sctp
parent1eed677933b816978abc4e3e18ecae5f254cb9be (diff)
sctp: hold transport before we access t->asoc in sctp proc
Previously, before rhashtable, /proc assoc listing was done by read-locking the entire hash entry and dumping all assocs at once, so we were sure that the assoc wasn't freed because it wouldn't be possible to remove it from the hash meanwhile. Now we use rhashtable to list transports, and dump entries one by one. That is, now we have to check if the assoc is still a good one, as the transport we got may be being freed. Signed-off-by: Xin Long <lucien.xin@gmail.com> Reviewed-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp')
-rw-r--r--net/sctp/proc.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index 684c5b31563b..c74a810150aa 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -380,6 +380,8 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
}
transport = (struct sctp_transport *)v;
+ if (!sctp_transport_hold(transport))
+ return 0;
assoc = transport->asoc;
epb = &assoc->base;
sk = epb->sk;
@@ -412,6 +414,8 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
sk->sk_rcvbuf);
seq_printf(seq, "\n");
+ sctp_transport_put(transport);
+
return 0;
}
@@ -489,6 +493,8 @@ static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
}
tsp = (struct sctp_transport *)v;
+ if (!sctp_transport_hold(tsp))
+ return 0;
assoc = tsp->asoc;
list_for_each_entry_rcu(tsp, &assoc->peer.transport_addr_list,
@@ -544,6 +550,8 @@ static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
seq_printf(seq, "\n");
}
+ sctp_transport_put(tsp);
+
return 0;
}