Commit fb863b8b authored by David S. Miller's avatar David S. Miller

Merge tag 'batman-adv-fix-for-davem' of git://git.open-mesh.org/linux-merge

Included changes:
- fix parsing of user typed protocol string to avoid random memory access in
  some cases
- check pskb_trim_rcsum() return value
- prevent DAT from sending ARP replies when not needed
- reorder the main clean up routine to prevent race conditions
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 2fbd9679 a4361860
...@@ -837,6 +837,19 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv, ...@@ -837,6 +837,19 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst); dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst);
if (dat_entry) { if (dat_entry) {
/* If the ARP request is destined for a local client the local
* client will answer itself. DAT would only generate a
* duplicate packet.
*
* Moreover, if the soft-interface is enslaved into a bridge, an
* additional DAT answer may trigger kernel warnings about
* a packet coming from the wrong port.
*/
if (batadv_is_my_client(bat_priv, dat_entry->mac_addr)) {
ret = true;
goto out;
}
skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src, skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src,
bat_priv->soft_iface, ip_dst, hw_src, bat_priv->soft_iface, ip_dst, hw_src,
dat_entry->mac_addr, hw_src); dat_entry->mac_addr, hw_src);
......
...@@ -163,14 +163,22 @@ void batadv_mesh_free(struct net_device *soft_iface) ...@@ -163,14 +163,22 @@ void batadv_mesh_free(struct net_device *soft_iface)
batadv_vis_quit(bat_priv); batadv_vis_quit(bat_priv);
batadv_gw_node_purge(bat_priv); batadv_gw_node_purge(bat_priv);
batadv_originator_free(bat_priv);
batadv_nc_free(bat_priv); batadv_nc_free(bat_priv);
batadv_dat_free(bat_priv);
batadv_bla_free(bat_priv);
/* Free the TT and the originator tables only after having terminated
* all the other depending components which may use these structures for
* their purposes.
*/
batadv_tt_free(bat_priv); batadv_tt_free(bat_priv);
batadv_bla_free(bat_priv); /* Since the originator table clean up routine is accessing the TT
* tables as well, it has to be invoked after the TT tables have been
batadv_dat_free(bat_priv); * freed and marked as empty. This ensures that no cleanup RCU callbacks
* accessing the TT data are scheduled for later execution.
*/
batadv_originator_free(bat_priv);
free_percpu(bat_priv->bat_counters); free_percpu(bat_priv->bat_counters);
...@@ -475,7 +483,7 @@ static int batadv_param_set_ra(const char *val, const struct kernel_param *kp) ...@@ -475,7 +483,7 @@ static int batadv_param_set_ra(const char *val, const struct kernel_param *kp)
char *algo_name = (char *)val; char *algo_name = (char *)val;
size_t name_len = strlen(algo_name); size_t name_len = strlen(algo_name);
if (algo_name[name_len - 1] == '\n') if (name_len > 0 && algo_name[name_len - 1] == '\n')
algo_name[name_len - 1] = '\0'; algo_name[name_len - 1] = '\0';
bat_algo_ops = batadv_algo_get(algo_name); bat_algo_ops = batadv_algo_get(algo_name);
......
...@@ -1514,6 +1514,7 @@ batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb, ...@@ -1514,6 +1514,7 @@ batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb,
struct ethhdr *ethhdr, ethhdr_tmp; struct ethhdr *ethhdr, ethhdr_tmp;
uint8_t *orig_dest, ttl, ttvn; uint8_t *orig_dest, ttl, ttvn;
unsigned int coding_len; unsigned int coding_len;
int err;
/* Save headers temporarily */ /* Save headers temporarily */
memcpy(&coded_packet_tmp, skb->data, sizeof(coded_packet_tmp)); memcpy(&coded_packet_tmp, skb->data, sizeof(coded_packet_tmp));
...@@ -1568,8 +1569,11 @@ batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb, ...@@ -1568,8 +1569,11 @@ batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb,
coding_len); coding_len);
/* Resize decoded skb if decoded with larger packet */ /* Resize decoded skb if decoded with larger packet */
if (nc_packet->skb->len > coding_len + h_size) if (nc_packet->skb->len > coding_len + h_size) {
pskb_trim_rcsum(skb, coding_len + h_size); err = pskb_trim_rcsum(skb, coding_len + h_size);
if (err)
return NULL;
}
/* Create decoded unicast packet */ /* Create decoded unicast packet */
unicast_packet = (struct batadv_unicast_packet *)skb->data; unicast_packet = (struct batadv_unicast_packet *)skb->data;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment