Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=aaa53c4aba14f14de06419a20e552fe2d8823a33
Commit:     aaa53c4aba14f14de06419a20e552fe2d8823a33
Parent:     f424bb9efaee90b752aabcb4e5e95920ee9580bb
Author:     Benjamin Thery <[EMAIL PROTECTED]>
AuthorDate: Fri Aug 24 23:12:08 2007 -0700
Committer:  David S. Miller <[EMAIL PROTECTED]>
CommitDate: Sun Aug 26 18:35:43 2007 -0700

    [NET]: Fix crash in dev_mc_sync()/dev_mc_unsync()
    
    This patch fixes a crash that may occur when the routine dev_mc_sync()
    deletes an address from the list it is currently going through. It
    saves the pointer to the next element before deleting the current one.
    The problem may also exist in dev_mc_unsync().
    
    Signed-off-by: Benjamin Thery <[EMAIL PROTECTED]>
    Acked-by: Patrick McHardy <[EMAIL PROTECTED]>
    Signed-off-by: David S. Miller <[EMAIL PROTECTED]>
---
 net/core/dev_mcast.c |   14 ++++++++++----
 1 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c
index 99aece1..20330c5 100644
--- a/net/core/dev_mcast.c
+++ b/net/core/dev_mcast.c
@@ -116,11 +116,13 @@ int dev_mc_add(struct net_device *dev, void *addr, int 
alen, int glbl)
  */
 int dev_mc_sync(struct net_device *to, struct net_device *from)
 {
-       struct dev_addr_list *da;
+       struct dev_addr_list *da, *next;
        int err = 0;
 
        netif_tx_lock_bh(to);
-       for (da = from->mc_list; da != NULL; da = da->next) {
+       da = from->mc_list;
+       while (da != NULL) {
+               next = da->next;
                if (!da->da_synced) {
                        err = __dev_addr_add(&to->mc_list, &to->mc_count,
                                             da->da_addr, da->da_addrlen, 0);
@@ -134,6 +136,7 @@ int dev_mc_sync(struct net_device *to, struct net_device 
*from)
                        __dev_addr_delete(&from->mc_list, &from->mc_count,
                                          da->da_addr, da->da_addrlen, 0);
                }
+               da = next;
        }
        if (!err)
                __dev_set_rx_mode(to);
@@ -156,12 +159,14 @@ EXPORT_SYMBOL(dev_mc_sync);
  */
 void dev_mc_unsync(struct net_device *to, struct net_device *from)
 {
-       struct dev_addr_list *da;
+       struct dev_addr_list *da, *next;
 
        netif_tx_lock_bh(from);
        netif_tx_lock_bh(to);
 
-       for (da = from->mc_list; da != NULL; da = da->next) {
+       da = from->mc_list;
+       while (da != NULL) {
+               next = da->next;
                if (!da->da_synced)
                        continue;
                __dev_addr_delete(&to->mc_list, &to->mc_count,
@@ -169,6 +174,7 @@ void dev_mc_unsync(struct net_device *to, struct net_device 
*from)
                da->da_synced = 0;
                __dev_addr_delete(&from->mc_list, &from->mc_count,
                                  da->da_addr, da->da_addrlen, 0);
+               da = next;
        }
        __dev_set_rx_mode(to);
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to