[linux-next] LinuxNextTracking branch, master, updated. next-20150818

batman at open-mesh.org batman at open-mesh.org
Wed Aug 19 00:15:54 CEST 2015


The following commit has been merged in the master branch:
commit c1f066d4ee0bde4bb0ff4ac295218b631729e0de
Merge: 2bd736fa0d8a1da90e6ccaa6a79e56a8d2ae60c4 53cf037bf846417fd92dc92ddf97267f69b110f4
Author: David S. Miller <davem at davemloft.net>
Date:   Mon Aug 17 14:31:42 2015 -0700

    Merge tag 'batman-adv-for-davem' of git://git.open-mesh.org/linux-merge
    
    Antonio Quartulli says:
    
    ====================
    Included changes:
    - avoid integer overflow in GW selection routine
    - prevent race condition by making capability bit changes atomic (use
      clear/set/test_bit)
    - fix synchronization issue in mcast tvlv handler
    - fix crash on double list removal of TT Request objects
    - fix leak by puring packets enqueued for sending upon iface removal
    - ensure network header pointer is set in skb
    ====================
    
    Signed-off-by: David S. Miller <davem at davemloft.net>

diff --combined net/batman-adv/distributed-arp-table.c
index 6d0b471,1cfba20..cc7d87d
--- a/net/batman-adv/distributed-arp-table.c
+++ b/net/batman-adv/distributed-arp-table.c
@@@ -19,6 -19,7 +19,7 @@@
  #include "main.h"
  
  #include <linux/atomic.h>
+ #include <linux/bitops.h>
  #include <linux/byteorder/generic.h>
  #include <linux/errno.h>
  #include <linux/etherdevice.h>
@@@ -453,7 -454,7 +454,7 @@@ static bool batadv_is_orig_node_eligibl
  	int j;
  
  	/* check if orig node candidate is running DAT */
- 	if (!(candidate->capabilities & BATADV_ORIG_CAPA_HAS_DAT))
+ 	if (!test_bit(BATADV_ORIG_CAPA_HAS_DAT, &candidate->capabilities))
  		goto out;
  
  	/* Check if this node has already been selected... */
@@@ -713,9 -714,9 +714,9 @@@ static void batadv_dat_tvlv_ogm_handler
  					   uint16_t tvlv_value_len)
  {
  	if (flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND)
- 		orig->capabilities &= ~BATADV_ORIG_CAPA_HAS_DAT;
+ 		clear_bit(BATADV_ORIG_CAPA_HAS_DAT, &orig->capabilities);
  	else
- 		orig->capabilities |= BATADV_ORIG_CAPA_HAS_DAT;
+ 		set_bit(BATADV_ORIG_CAPA_HAS_DAT, &orig->capabilities);
  }
  
  /**
@@@ -1138,9 -1139,6 +1139,9 @@@ void batadv_dat_snoop_outgoing_arp_repl
   * @bat_priv: the bat priv with all the soft interface information
   * @skb: packet to check
   * @hdr_size: size of the encapsulation header
 + *
 + * Returns true if the packet was snooped and consumed by DAT. False if the
 + * packet has to be delivered to the interface
   */
  bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
  					 struct sk_buff *skb, int hdr_size)
@@@ -1148,7 -1146,7 +1149,7 @@@
  	uint16_t type;
  	__be32 ip_src, ip_dst;
  	uint8_t *hw_src, *hw_dst;
 -	bool ret = false;
 +	bool dropped = false;
  	unsigned short vid;
  
  	if (!atomic_read(&bat_priv->distributed_arp_table))
@@@ -1177,17 -1175,12 +1178,17 @@@
  	/* if this REPLY is directed to a client of mine, let's deliver the
  	 * packet to the interface
  	 */
 -	ret = !batadv_is_my_client(bat_priv, hw_dst, vid);
 +	dropped = !batadv_is_my_client(bat_priv, hw_dst, vid);
 +
 +	/* if this REPLY is sent on behalf of a client of mine, let's drop the
 +	 * packet because the client will reply by itself
 +	 */
 +	dropped |= batadv_is_my_client(bat_priv, hw_src, vid);
  out:
 -	if (ret)
 +	if (dropped)
  		kfree_skb(skb);
 -	/* if ret == false -> packet has to be delivered to the interface */
 -	return ret;
 +	/* if dropped == false -> deliver to the interface */
 +	return dropped;
  }
  
  /**
diff --combined net/batman-adv/gateway_client.c
index cffa92d,4ac24d8..6012e2b
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@@ -153,15 -153,11 +153,11 @@@ batadv_gw_get_best_gw_node(struct batad
  	struct batadv_neigh_node *router;
  	struct batadv_neigh_ifinfo *router_ifinfo;
  	struct batadv_gw_node *gw_node, *curr_gw = NULL;
- 	uint32_t max_gw_factor = 0, tmp_gw_factor = 0;
- 	uint32_t gw_divisor;
+ 	uint64_t max_gw_factor = 0, tmp_gw_factor = 0;
  	uint8_t max_tq = 0;
  	uint8_t tq_avg;
  	struct batadv_orig_node *orig_node;
  
- 	gw_divisor = BATADV_TQ_LOCAL_WINDOW_SIZE * BATADV_TQ_LOCAL_WINDOW_SIZE;
- 	gw_divisor *= 64;
- 
  	rcu_read_lock();
  	hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.list, list) {
  		if (gw_node->deleted)
@@@ -187,7 -183,7 +183,7 @@@
  			tmp_gw_factor = tq_avg * tq_avg;
  			tmp_gw_factor *= gw_node->bandwidth_down;
  			tmp_gw_factor *= 100 * 100;
- 			tmp_gw_factor /= gw_divisor;
+ 			tmp_gw_factor >>= 18;
  
  			if ((tmp_gw_factor > max_gw_factor) ||
  			    ((tmp_gw_factor == max_gw_factor) &&
@@@ -439,8 -435,6 +435,8 @@@ static void batadv_gw_node_add(struct b
  
  	INIT_HLIST_NODE(&gw_node->list);
  	gw_node->orig_node = orig_node;
 +	gw_node->bandwidth_down = ntohl(gateway->bandwidth_down);
 +	gw_node->bandwidth_up = ntohl(gateway->bandwidth_up);
  	atomic_set(&gw_node->refcount, 1);
  
  	spin_lock_bh(&bat_priv->gw.list_lock);
diff --combined net/batman-adv/soft-interface.c
index a2fc843,926292d..51cda3a
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@@ -202,6 -202,7 +202,7 @@@ static int batadv_interface_tx(struct s
  	int gw_mode;
  	enum batadv_forw_mode forw_mode;
  	struct batadv_orig_node *mcast_single_orig = NULL;
+ 	int network_offset = ETH_HLEN;
  
  	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
  		goto dropped;
@@@ -214,14 -215,18 +215,18 @@@
  	case ETH_P_8021Q:
  		vhdr = vlan_eth_hdr(skb);
  
- 		if (vhdr->h_vlan_encapsulated_proto != ethertype)
+ 		if (vhdr->h_vlan_encapsulated_proto != ethertype) {
+ 			network_offset += VLAN_HLEN;
  			break;
+ 		}
  
  		/* fall through */
  	case ETH_P_BATMAN:
  		goto dropped;
  	}
  
+ 	skb_set_network_header(skb, network_offset);
+ 
  	if (batadv_bla_tx(bat_priv, skb, vid))
  		goto dropped;
  
@@@ -479,9 -484,6 +484,9 @@@ out
   */
  void batadv_softif_vlan_free_ref(struct batadv_softif_vlan *vlan)
  {
 +	if (!vlan)
 +		return;
 +
  	if (atomic_dec_and_test(&vlan->refcount)) {
  		spin_lock_bh(&vlan->bat_priv->softif_vlan_list_lock);
  		hlist_del_rcu(&vlan->list);
diff --combined net/batman-adv/translation-table.c
index 5e953297,cd35bb8..db06de2
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@@ -19,6 -19,7 +19,7 @@@
  #include "main.h"
  
  #include <linux/atomic.h>
+ #include <linux/bitops.h>
  #include <linux/bug.h>
  #include <linux/byteorder/generic.h>
  #include <linux/compiler.h>
@@@ -594,9 -595,6 +595,9 @@@ bool batadv_tt_local_add(struct net_dev
  
  	/* increase the refcounter of the related vlan */
  	vlan = batadv_softif_vlan_get(bat_priv, vid);
 +	if (WARN(!vlan, "adding TT local entry %pM to non-existent VLAN %d",
 +		 addr, BATADV_PRINT_VID(vid)))
 +		goto out;
  
  	batadv_dbg(BATADV_DBG_TT, bat_priv,
  		   "Creating new local tt entry: %pM (vid: %d, ttvn: %d)\n",
@@@ -1037,7 -1035,6 +1038,7 @@@ uint16_t batadv_tt_local_remove(struct 
  	struct batadv_tt_local_entry *tt_local_entry;
  	uint16_t flags, curr_flags = BATADV_NO_FLAGS;
  	struct batadv_softif_vlan *vlan;
 +	void *tt_entry_exists;
  
  	tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid);
  	if (!tt_local_entry)
@@@ -1065,22 -1062,11 +1066,22 @@@
  	 * immediately purge it
  	 */
  	batadv_tt_local_event(bat_priv, tt_local_entry, BATADV_TT_CLIENT_DEL);
 -	hlist_del_rcu(&tt_local_entry->common.hash_entry);
 +
 +	tt_entry_exists = batadv_hash_remove(bat_priv->tt.local_hash,
 +					     batadv_compare_tt,
 +					     batadv_choose_tt,
 +					     &tt_local_entry->common);
 +	if (!tt_entry_exists)
 +		goto out;
 +
 +	/* extra call to free the local tt entry */
  	batadv_tt_local_entry_free_ref(tt_local_entry);
  
  	/* decrease the reference held for this vlan */
  	vlan = batadv_softif_vlan_get(bat_priv, vid);
 +	if (!vlan)
 +		goto out;
 +
  	batadv_softif_vlan_free_ref(vlan);
  	batadv_softif_vlan_free_ref(vlan);
  
@@@ -1181,10 -1167,8 +1182,10 @@@ static void batadv_tt_local_table_free(
  			/* decrease the reference held for this vlan */
  			vlan = batadv_softif_vlan_get(bat_priv,
  						      tt_common_entry->vid);
 -			batadv_softif_vlan_free_ref(vlan);
 -			batadv_softif_vlan_free_ref(vlan);
 +			if (vlan) {
 +				batadv_softif_vlan_free_ref(vlan);
 +				batadv_softif_vlan_free_ref(vlan);
 +			}
  
  			batadv_tt_local_entry_free_ref(tt_local);
  		}
@@@ -1879,7 -1863,7 +1880,7 @@@ void batadv_tt_global_del_orig(struct b
  		}
  		spin_unlock_bh(list_lock);
  	}
- 	orig_node->capa_initialized &= ~BATADV_ORIG_CAPA_HAS_TT;
+ 	clear_bit(BATADV_ORIG_CAPA_HAS_TT, &orig_node->capa_initialized);
  }
  
  static bool batadv_tt_global_to_purge(struct batadv_tt_global_entry *tt_global,
@@@ -2212,7 -2196,7 +2213,7 @@@ static void batadv_tt_req_list_free(str
  	spin_lock_bh(&bat_priv->tt.req_list_lock);
  
  	list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
- 		list_del(&node->list);
+ 		list_del_init(&node->list);
  		kfree(node);
  	}
  
@@@ -2248,7 -2232,7 +2249,7 @@@ static void batadv_tt_req_purge(struct 
  	list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
  		if (batadv_has_timed_out(node->issued_at,
  					 BATADV_TT_REQUEST_TIMEOUT)) {
- 			list_del(&node->list);
+ 			list_del_init(&node->list);
  			kfree(node);
  		}
  	}
@@@ -2530,7 -2514,8 +2531,8 @@@ out
  		batadv_hardif_free_ref(primary_if);
  	if (ret && tt_req_node) {
  		spin_lock_bh(&bat_priv->tt.req_list_lock);
- 		list_del(&tt_req_node->list);
+ 		/* list_del_init() verifies tt_req_node still is in the list */
+ 		list_del_init(&tt_req_node->list);
  		spin_unlock_bh(&bat_priv->tt.req_list_lock);
  		kfree(tt_req_node);
  	}
@@@ -2838,7 -2823,7 +2840,7 @@@ static void _batadv_tt_update_changes(s
  				return;
  		}
  	}
- 	orig_node->capa_initialized |= BATADV_ORIG_CAPA_HAS_TT;
+ 	set_bit(BATADV_ORIG_CAPA_HAS_TT, &orig_node->capa_initialized);
  }
  
  static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv,
@@@ -2967,7 -2952,7 +2969,7 @@@ static void batadv_handle_tt_response(s
  	list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
  		if (!batadv_compare_eth(node->addr, resp_src))
  			continue;
- 		list_del(&node->list);
+ 		list_del_init(&node->list);
  		kfree(node);
  	}
  
@@@ -3224,10 -3209,8 +3226,10 @@@ static void batadv_tt_local_purge_pendi
  
  			/* decrease the reference held for this vlan */
  			vlan = batadv_softif_vlan_get(bat_priv, tt_common->vid);
 -			batadv_softif_vlan_free_ref(vlan);
 -			batadv_softif_vlan_free_ref(vlan);
 +			if (vlan) {
 +				batadv_softif_vlan_free_ref(vlan);
 +				batadv_softif_vlan_free_ref(vlan);
 +			}
  
  			batadv_tt_local_entry_free_ref(tt_local);
  		}
@@@ -3340,7 -3323,8 +3342,8 @@@ static void batadv_tt_update_orig(struc
  	bool has_tt_init;
  
  	tt_vlan = (struct batadv_tvlv_tt_vlan_data *)tt_buff;
- 	has_tt_init = orig_node->capa_initialized & BATADV_ORIG_CAPA_HAS_TT;
+ 	has_tt_init = test_bit(BATADV_ORIG_CAPA_HAS_TT,
+ 			       &orig_node->capa_initialized);
  
  	/* orig table not initialised AND first diff is in the OGM OR the ttvn
  	 * increased by one -> we can apply the attached changes

-- 
LinuxNextTracking


More information about the linux-merge mailing list