[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 <benjamin.thery@bull.net>
Acked-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by Benjamin Thery and committed by David S. Miller aaa53c4a f424bb9e

+10 -4
+10 -4
net/core/dev_mcast.c
··· 116 116 */ 117 117 int dev_mc_sync(struct net_device *to, struct net_device *from) 118 118 { 119 - struct dev_addr_list *da; 119 + struct dev_addr_list *da, *next; 120 120 int err = 0; 121 121 122 122 netif_tx_lock_bh(to); 123 - for (da = from->mc_list; da != NULL; da = da->next) { 123 + da = from->mc_list; 124 + while (da != NULL) { 125 + next = da->next; 124 126 if (!da->da_synced) { 125 127 err = __dev_addr_add(&to->mc_list, &to->mc_count, 126 128 da->da_addr, da->da_addrlen, 0); ··· 136 134 __dev_addr_delete(&from->mc_list, &from->mc_count, 137 135 da->da_addr, da->da_addrlen, 0); 138 136 } 137 + da = next; 139 138 } 140 139 if (!err) 141 140 __dev_set_rx_mode(to); ··· 159 156 */ 160 157 void dev_mc_unsync(struct net_device *to, struct net_device *from) 161 158 { 162 - struct dev_addr_list *da; 159 + struct dev_addr_list *da, *next; 163 160 164 161 netif_tx_lock_bh(from); 165 162 netif_tx_lock_bh(to); 166 163 167 - for (da = from->mc_list; da != NULL; da = da->next) { 164 + da = from->mc_list; 165 + while (da != NULL) { 166 + next = da->next; 168 167 if (!da->da_synced) 169 168 continue; 170 169 __dev_addr_delete(&to->mc_list, &to->mc_count, ··· 174 169 da->da_synced = 0; 175 170 __dev_addr_delete(&from->mc_list, &from->mc_count, 176 171 da->da_addr, da->da_addrlen, 0); 172 + da = next; 177 173 } 178 174 __dev_set_rx_mode(to); 179 175