aboutsummaryrefslogtreecommitdiff
path: root/net/sctp/ipv6.c
diff options
context:
space:
mode:
authorChidambar 'ilLogict' Zinnoury <illogict@online.fr>2008-03-11 18:05:02 -0700
committerDavid S. Miller <davem@davemloft.net>2008-03-11 18:05:02 -0700
commit22626216c46f2ec86287e75ea86dd9ac3df54265 (patch)
treeee7fb381a17fb8105b7f2f8cd40cc4b587d064d0 /net/sctp/ipv6.c
parentb2211a361a4289c83971f89da53fe2eb9e72769d (diff)
[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/ipv6.c')
-rw-r--r--net/sctp/ipv6.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 87f940587d5..9aa0733aee8 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -89,6 +89,7 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev,
struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
struct sctp_sockaddr_entry *addr = NULL;
struct sctp_sockaddr_entry *temp;
+ int found = 0;
switch (ev) {
case NETDEV_UP:
@@ -111,13 +112,14 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev,
&sctp_local_addr_list, list) {
if (ipv6_addr_equal(&addr->a.v6.sin6_addr,
&ifa->addr)) {
+ found = 1;
addr->valid = 0;
list_del_rcu(&addr->list);
break;
}
}
spin_unlock_bh(&sctp_local_addr_lock);
- if (addr && !addr->valid)
+ if (found)
call_rcu(&addr->rcu, sctp_local_addr_free);
break;
}