aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/vis.c
diff options
context:
space:
mode:
authorMarek Lindner <lindner_marek@yahoo.de>2011-04-20 09:40:58 -0400
committerSven Eckelmann <sven@narfation.org>2011-05-01 16:49:03 -0400
commit32ae9b221e788413ce68feaae2ca39e406211a0a (patch)
treed827f989976a28fea5cdcb349c308baa98182c35 /net/batman-adv/vis.c
parent71e4aa9c465fd66c110667ab5d620fb6a4ef2157 (diff)
batman-adv: Make bat_priv->primary_if an rcu protected pointer
The rcu protected macros rcu_dereference() and rcu_assign_pointer() for the bat_priv->primary_if need to be used, as well as spin/rcu locking. Otherwise we might end up using a primary_if pointer pointing to already freed memory. Signed-off-by: Marek Lindner <lindner_marek@yahoo.de> Signed-off-by: Sven Eckelmann <sven@narfation.org>
Diffstat (limited to 'net/batman-adv/vis.c')
-rw-r--r--net/batman-adv/vis.c37
1 files changed, 26 insertions, 11 deletions
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c
index d4cc4f5399f4..c8f571d3b5d4 100644
--- a/net/batman-adv/vis.c
+++ b/net/batman-adv/vis.c
@@ -204,6 +204,7 @@ static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry,
204 204
205int vis_seq_print_text(struct seq_file *seq, void *offset) 205int vis_seq_print_text(struct seq_file *seq, void *offset)
206{ 206{
207 struct hard_iface *primary_if;
207 struct hlist_node *node; 208 struct hlist_node *node;
208 struct hlist_head *head; 209 struct hlist_head *head;
209 struct vis_info *info; 210 struct vis_info *info;
@@ -215,15 +216,18 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
215 HLIST_HEAD(vis_if_list); 216 HLIST_HEAD(vis_if_list);
216 struct if_list_entry *entry; 217 struct if_list_entry *entry;
217 struct hlist_node *pos, *n; 218 struct hlist_node *pos, *n;
218 int i, j; 219 int i, j, ret = 0;
219 int vis_server = atomic_read(&bat_priv->vis_mode); 220 int vis_server = atomic_read(&bat_priv->vis_mode);
220 size_t buff_pos, buf_size; 221 size_t buff_pos, buf_size;
221 char *buff; 222 char *buff;
222 int compare; 223 int compare;
223 224
224 if ((!bat_priv->primary_if) || 225 primary_if = primary_if_get_selected(bat_priv);
225 (vis_server == VIS_TYPE_CLIENT_UPDATE)) 226 if (!primary_if)
226 return 0; 227 goto out;
228
229 if (vis_server == VIS_TYPE_CLIENT_UPDATE)
230 goto out;
227 231
228 buf_size = 1; 232 buf_size = 1;
229 /* Estimate length */ 233 /* Estimate length */
@@ -270,7 +274,8 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
270 buff = kmalloc(buf_size, GFP_ATOMIC); 274 buff = kmalloc(buf_size, GFP_ATOMIC);
271 if (!buff) { 275 if (!buff) {
272 spin_unlock_bh(&bat_priv->vis_hash_lock); 276 spin_unlock_bh(&bat_priv->vis_hash_lock);
273 return -ENOMEM; 277 ret = -ENOMEM;
278 goto out;
274 } 279 }
275 buff[0] = '\0'; 280 buff[0] = '\0';
276 buff_pos = 0; 281 buff_pos = 0;
@@ -328,7 +333,10 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
328 seq_printf(seq, "%s", buff); 333 seq_printf(seq, "%s", buff);
329 kfree(buff); 334 kfree(buff);
330 335
331 return 0; 336out:
337 if (primary_if)
338 hardif_free_ref(primary_if);
339 return ret;
332} 340}
333 341
334/* add the info packet to the send list, if it was not 342/* add the info packet to the send list, if it was not
@@ -815,16 +823,20 @@ out:
815/* only send one vis packet. called from send_vis_packets() */ 823/* only send one vis packet. called from send_vis_packets() */
816static void send_vis_packet(struct bat_priv *bat_priv, struct vis_info *info) 824static void send_vis_packet(struct bat_priv *bat_priv, struct vis_info *info)
817{ 825{
826 struct hard_iface *primary_if;
818 struct vis_packet *packet; 827 struct vis_packet *packet;
819 828
829 primary_if = primary_if_get_selected(bat_priv);
830 if (!primary_if)
831 goto out;
832
820 packet = (struct vis_packet *)info->skb_packet->data; 833 packet = (struct vis_packet *)info->skb_packet->data;
821 if (packet->ttl < 2) { 834 if (packet->ttl < 2) {
822 pr_debug("Error - can't send vis packet: ttl exceeded\n"); 835 pr_debug("Error - can't send vis packet: ttl exceeded\n");
823 return; 836 goto out;
824 } 837 }
825 838
826 memcpy(packet->sender_orig, bat_priv->primary_if->net_dev->dev_addr, 839 memcpy(packet->sender_orig, primary_if->net_dev->dev_addr, ETH_ALEN);
827 ETH_ALEN);
828 packet->ttl--; 840 packet->ttl--;
829 841
830 if (is_broadcast_ether_addr(packet->target_orig)) 842 if (is_broadcast_ether_addr(packet->target_orig))
@@ -832,6 +844,10 @@ static void send_vis_packet(struct bat_priv *bat_priv, struct vis_info *info)
832 else 844 else
833 unicast_vis_packet(bat_priv, info); 845 unicast_vis_packet(bat_priv, info);
834 packet->ttl++; /* restore TTL */ 846 packet->ttl++; /* restore TTL */
847
848out:
849 if (primary_if)
850 hardif_free_ref(primary_if);
835} 851}
836 852
837/* called from timer; send (and maybe generate) vis packet. */ 853/* called from timer; send (and maybe generate) vis packet. */
@@ -858,8 +874,7 @@ static void send_vis_packets(struct work_struct *work)
858 kref_get(&info->refcount); 874 kref_get(&info->refcount);
859 spin_unlock_bh(&bat_priv->vis_hash_lock); 875 spin_unlock_bh(&bat_priv->vis_hash_lock);
860 876
861 if (bat_priv->primary_if) 877 send_vis_packet(bat_priv, info);
862 send_vis_packet(bat_priv, info);
863 878
864 spin_lock_bh(&bat_priv->vis_hash_lock); 879 spin_lock_bh(&bat_priv->vis_hash_lock);
865 send_list_del(info); 880 send_list_del(info);