Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e5ac5da8 authored by David S. Miller's avatar David S. Miller
Browse files

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



Included change:
- reassign pointers to data after skb reallocation to avoid kernel paging errors

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 4209423c 9d2c9488
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -1529,6 +1529,8 @@ int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
 * in these cases, the skb is further handled by this function and
 * returns 1, otherwise it returns 0 and the caller shall further
 * process the skb.
 *
 * This call might reallocate skb data.
 */
int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb,
		  unsigned short vid)
+12 −1
Original line number Diff line number Diff line
@@ -508,6 +508,7 @@ int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset)
	return 0;
}

/* this call might reallocate skb data */
static bool batadv_is_type_dhcprequest(struct sk_buff *skb, int header_len)
{
	int ret = false;
@@ -568,6 +569,7 @@ static bool batadv_is_type_dhcprequest(struct sk_buff *skb, int header_len)
	return ret;
}

/* this call might reallocate skb data */
bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len)
{
	struct ethhdr *ethhdr;
@@ -619,6 +621,12 @@ bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len)

	if (!pskb_may_pull(skb, *header_len + sizeof(*udphdr)))
		return false;

	/* skb->data might have been reallocated by pskb_may_pull() */
	ethhdr = (struct ethhdr *)skb->data;
	if (ntohs(ethhdr->h_proto) == ETH_P_8021Q)
		ethhdr = (struct ethhdr *)(skb->data + VLAN_HLEN);

	udphdr = (struct udphdr *)(skb->data + *header_len);
	*header_len += sizeof(*udphdr);

@@ -634,12 +642,14 @@ bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len)
	return true;
}

/* this call might reallocate skb data */
bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
			    struct sk_buff *skb, struct ethhdr *ethhdr)
			    struct sk_buff *skb)
{
	struct batadv_neigh_node *neigh_curr = NULL, *neigh_old = NULL;
	struct batadv_orig_node *orig_dst_node = NULL;
	struct batadv_gw_node *curr_gw = NULL;
	struct ethhdr *ethhdr;
	bool ret, out_of_range = false;
	unsigned int header_len = 0;
	uint8_t curr_tq_avg;
@@ -648,6 +658,7 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
	if (!ret)
		goto out;

	ethhdr = (struct ethhdr *)skb->data;
	orig_dst_node = batadv_transtable_search(bat_priv, ethhdr->h_source,
						 ethhdr->h_dest);
	if (!orig_dst_node)
+1 −2
Original line number Diff line number Diff line
@@ -34,7 +34,6 @@ void batadv_gw_node_delete(struct batadv_priv *bat_priv,
void batadv_gw_node_purge(struct batadv_priv *bat_priv);
int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset);
bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len);
bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
			    struct sk_buff *skb, struct ethhdr *ethhdr);
bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, struct sk_buff *skb);

#endif /* _NET_BATMAN_ADV_GATEWAY_CLIENT_H_ */
+8 −1
Original line number Diff line number Diff line
@@ -180,6 +180,9 @@ static int batadv_interface_tx(struct sk_buff *skb,
	if (batadv_bla_tx(bat_priv, skb, vid))
		goto dropped;

	/* skb->data might have been reallocated by batadv_bla_tx() */
	ethhdr = (struct ethhdr *)skb->data;

	/* Register the client MAC in the transtable */
	if (!is_multicast_ether_addr(ethhdr->h_source))
		batadv_tt_local_add(soft_iface, ethhdr->h_source, skb->skb_iif);
@@ -220,6 +223,10 @@ static int batadv_interface_tx(struct sk_buff *skb,
		default:
			break;
		}

		/* reminder: ethhdr might have become unusable from here on
		 * (batadv_gw_is_dhcp_target() might have reallocated skb data)
		 */
	}

	/* ethernet packet should be broadcasted */
@@ -266,7 +273,7 @@ static int batadv_interface_tx(struct sk_buff *skb,
	/* unicast packet */
	} else {
		if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_OFF) {
			ret = batadv_gw_out_of_range(bat_priv, skb, ethhdr);
			ret = batadv_gw_out_of_range(bat_priv, skb);
			if (ret)
				goto dropped;
		}
+10 −3
Original line number Diff line number Diff line
@@ -326,7 +326,9 @@ static bool batadv_unicast_push_and_fill_skb(struct sk_buff *skb, int hdr_size,
 * @skb: the skb containing the payload to encapsulate
 * @orig_node: the destination node
 *
 * Returns false if the payload could not be encapsulated or true otherwise
 * Returns false if the payload could not be encapsulated or true otherwise.
 *
 * This call might reallocate skb data.
 */
static bool batadv_unicast_prepare_skb(struct sk_buff *skb,
				       struct batadv_orig_node *orig_node)
@@ -343,7 +345,9 @@ static bool batadv_unicast_prepare_skb(struct sk_buff *skb,
 * @orig_node: the destination node
 * @packet_subtype: the batman 4addr packet subtype to use
 *
 * Returns false if the payload could not be encapsulated or true otherwise
 * Returns false if the payload could not be encapsulated or true otherwise.
 *
 * This call might reallocate skb data.
 */
bool batadv_unicast_4addr_prepare_skb(struct batadv_priv *bat_priv,
				      struct sk_buff *skb,
@@ -401,7 +405,7 @@ int batadv_unicast_generic_send_skb(struct batadv_priv *bat_priv,
	struct batadv_neigh_node *neigh_node;
	int data_len = skb->len;
	int ret = NET_RX_DROP;
	unsigned int dev_mtu;
	unsigned int dev_mtu, header_len;

	/* get routing information */
	if (is_multicast_ether_addr(ethhdr->h_dest)) {
@@ -429,10 +433,12 @@ int batadv_unicast_generic_send_skb(struct batadv_priv *bat_priv,
	switch (packet_type) {
	case BATADV_UNICAST:
		batadv_unicast_prepare_skb(skb, orig_node);
		header_len = sizeof(struct batadv_unicast_packet);
		break;
	case BATADV_UNICAST_4ADDR:
		batadv_unicast_4addr_prepare_skb(bat_priv, skb, orig_node,
						 packet_subtype);
		header_len = sizeof(struct batadv_unicast_4addr_packet);
		break;
	default:
		/* this function supports UNICAST and UNICAST_4ADDR only. It
@@ -441,6 +447,7 @@ int batadv_unicast_generic_send_skb(struct batadv_priv *bat_priv,
		goto out;
	}

	ethhdr = (struct ethhdr *)(skb->data + header_len);
	unicast_packet = (struct batadv_unicast_packet *)skb->data;

	/* inform the destination node that we are still missing a correct route