aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorXin Long <lucien.xin@gmail.com>2016-01-21 12:49:08 -0500
committerDavid S. Miller <davem@davemloft.net>2016-01-28 18:59:32 -0500
commitfba4c330c5b9d1beeae08a42ed4430f5055e7f27 (patch)
tree22a304daa8d4cb74a609587a841e3f85a7b57348 /net
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')
-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)
380 } 380 }
381 381
382 transport = (struct sctp_transport *)v; 382 transport = (struct sctp_transport *)v;
383 if (!sctp_transport_hold(transport))
384 return 0;
383 assoc = transport->asoc; 385 assoc = transport->asoc;
384 epb = &assoc->base; 386 epb = &assoc->base;
385 sk = epb->sk; 387 sk = epb->sk;
@@ -412,6 +414,8 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
412 sk->sk_rcvbuf); 414 sk->sk_rcvbuf);
413 seq_printf(seq, "\n"); 415 seq_printf(seq, "\n");
414 416
417 sctp_transport_put(transport);
418
415 return 0; 419 return 0;
416} 420}
417 421
@@ -489,6 +493,8 @@ static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
489 } 493 }
490 494
491 tsp = (struct sctp_transport *)v; 495 tsp = (struct sctp_transport *)v;
496 if (!sctp_transport_hold(tsp))
497 return 0;
492 assoc = tsp->asoc; 498 assoc = tsp->asoc;
493 499
494 list_for_each_entry_rcu(tsp, &assoc->peer.transport_addr_list, 500 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)
544 seq_printf(seq, "\n"); 550 seq_printf(seq, "\n");
545 } 551 }
546 552
553 sctp_transport_put(tsp);
554
547 return 0; 555 return 0;
548} 556}
549 557