From e1a5382f978b67b5cc36eec65e6046730ce07714 Mon Sep 17 00:00:00 2001 From: Linus Lüssing Date: Mon, 14 Mar 2011 22:43:37 +0000 Subject: batman-adv: Make orig_node->router an rcu protected pointer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The rcu protected macros rcu_dereference() and rcu_assign_pointer() for the orig_node->router need to be used, as well as spin/rcu locking. Otherwise we might end up using a router pointer pointing to already freed memory. Therefore this commit introduces the safe getter method orig_node_get_router(). Signed-off-by: Linus Lüssing Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann --- net/batman-adv/icmp_socket.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) (limited to 'net/batman-adv/icmp_socket.c') diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c index 34ce56c358e..49079c25447 100644 --- a/net/batman-adv/icmp_socket.c +++ b/net/batman-adv/icmp_socket.c @@ -218,23 +218,13 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE) goto dst_unreach; - rcu_read_lock(); orig_node = orig_hash_find(bat_priv, icmp_packet->dst); - if (!orig_node) - goto unlock; - - neigh_node = orig_node->router; + goto dst_unreach; + neigh_node = orig_node_get_router(orig_node); if (!neigh_node) - goto unlock; - - if (!atomic_inc_not_zero(&neigh_node->refcount)) { - neigh_node = NULL; - goto unlock; - } - - rcu_read_unlock(); + goto dst_unreach; if (!neigh_node->if_incoming) goto dst_unreach; @@ -252,8 +242,6 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); goto out; -unlock: - rcu_read_unlock(); dst_unreach: icmp_packet->msg_type = DESTINATION_UNREACHABLE; bat_socket_add_packet(socket_client, icmp_packet, packet_len); -- cgit v1.2.3-18-g5258 From 32ae9b221e788413ce68feaae2ca39e406211a0a Mon Sep 17 00:00:00 2001 From: Marek Lindner Date: Wed, 20 Apr 2011 15:40:58 +0200 Subject: 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 Signed-off-by: Sven Eckelmann --- net/batman-adv/icmp_socket.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'net/batman-adv/icmp_socket.c') diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c index 49079c25447..fa22ba2bb83 100644 --- a/net/batman-adv/icmp_socket.c +++ b/net/batman-adv/icmp_socket.c @@ -153,6 +153,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, { struct socket_client *socket_client = file->private_data; struct bat_priv *bat_priv = socket_client->bat_priv; + struct hard_iface *primary_if = NULL; struct sk_buff *skb; struct icmp_packet_rr *icmp_packet; @@ -167,15 +168,21 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, return -EINVAL; } - if (!bat_priv->primary_if) - return -EFAULT; + primary_if = primary_if_get_selected(bat_priv); + + if (!primary_if) { + len = -EFAULT; + goto out; + } if (len >= sizeof(struct icmp_packet_rr)) packet_len = sizeof(struct icmp_packet_rr); skb = dev_alloc_skb(packet_len + sizeof(struct ethhdr)); - if (!skb) - return -ENOMEM; + if (!skb) { + len = -ENOMEM; + goto out; + } skb_reserve(skb, sizeof(struct ethhdr)); icmp_packet = (struct icmp_packet_rr *)skb_put(skb, packet_len); @@ -233,7 +240,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, goto dst_unreach; memcpy(icmp_packet->orig, - bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); + primary_if->net_dev->dev_addr, ETH_ALEN); if (packet_len == sizeof(struct icmp_packet_rr)) memcpy(icmp_packet->rr, @@ -248,6 +255,8 @@ dst_unreach: free_skb: kfree_skb(skb); out: + if (primary_if) + hardif_free_ref(primary_if); if (neigh_node) neigh_node_free_ref(neigh_node); if (orig_node) -- cgit v1.2.3-18-g5258