diff options
author | Chidambar 'ilLogict' Zinnoury <illogict@online.fr> | 2008-03-11 18:05:02 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-03-11 18:05:02 -0700 |
commit | 22626216c46f2ec86287e75ea86dd9ac3df54265 (patch) | |
tree | ee7fb381a17fb8105b7f2f8cd40cc4b587d064d0 /net/sctp/bind_addr.c | |
parent | b2211a361a4289c83971f89da53fe2eb9e72769d (diff) | |
download | lwn-22626216c46f2ec86287e75ea86dd9ac3df54265.tar.gz lwn-22626216c46f2ec86287e75ea86dd9ac3df54265.zip |
[SCTP]: Fix local_addr deletions during list traversals.
Since the lists are circular, we need to explicitely tag
the address to be deleted since we might end up freeing
the list head instead. This fixes some interesting SCTP
crashes.
Signed-off-by: Chidambar 'ilLogict' Zinnoury <illogict@online.fr>
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp/bind_addr.c')
-rw-r--r-- | net/sctp/bind_addr.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index a27511ebc4cb..ceefda025e2d 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c @@ -209,6 +209,7 @@ int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new, int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr) { struct sctp_sockaddr_entry *addr, *temp; + int found = 0; /* We hold the socket lock when calling this function, * and that acts as a writer synchronizing lock. @@ -216,13 +217,14 @@ int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr) list_for_each_entry_safe(addr, temp, &bp->address_list, list) { if (sctp_cmp_addr_exact(&addr->a, del_addr)) { /* Found the exact match. */ + found = 1; addr->valid = 0; list_del_rcu(&addr->list); break; } } - if (addr && !addr->valid) { + if (found) { call_rcu(&addr->rcu, sctp_local_addr_free); SCTP_DBG_OBJCNT_DEC(addr); return 0; |