Skip to content

Commit e5ac5da

Browse files
committed
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: David S. Miller <[email protected]>
2 parents 4209423 + 9d2c948 commit e5ac5da

File tree

5 files changed

+33
-7
lines changed

5 files changed

+33
-7
lines changed

net/batman-adv/bridge_loop_avoidance.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1529,6 +1529,8 @@ int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
15291529
* in these cases, the skb is further handled by this function and
15301530
* returns 1, otherwise it returns 0 and the caller shall further
15311531
* process the skb.
1532+
*
1533+
* This call might reallocate skb data.
15321534
*/
15331535
int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb,
15341536
unsigned short vid)

net/batman-adv/gateway_client.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,7 @@ int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset)
508508
return 0;
509509
}
510510

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

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

620622
if (!pskb_may_pull(skb, *header_len + sizeof(*udphdr)))
621623
return false;
624+
625+
/* skb->data might have been reallocated by pskb_may_pull() */
626+
ethhdr = (struct ethhdr *)skb->data;
627+
if (ntohs(ethhdr->h_proto) == ETH_P_8021Q)
628+
ethhdr = (struct ethhdr *)(skb->data + VLAN_HLEN);
629+
622630
udphdr = (struct udphdr *)(skb->data + *header_len);
623631
*header_len += sizeof(*udphdr);
624632

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

645+
/* this call might reallocate skb data */
637646
bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
638-
struct sk_buff *skb, struct ethhdr *ethhdr)
647+
struct sk_buff *skb)
639648
{
640649
struct batadv_neigh_node *neigh_curr = NULL, *neigh_old = NULL;
641650
struct batadv_orig_node *orig_dst_node = NULL;
642651
struct batadv_gw_node *curr_gw = NULL;
652+
struct ethhdr *ethhdr;
643653
bool ret, out_of_range = false;
644654
unsigned int header_len = 0;
645655
uint8_t curr_tq_avg;
@@ -648,6 +658,7 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
648658
if (!ret)
649659
goto out;
650660

661+
ethhdr = (struct ethhdr *)skb->data;
651662
orig_dst_node = batadv_transtable_search(bat_priv, ethhdr->h_source,
652663
ethhdr->h_dest);
653664
if (!orig_dst_node)

net/batman-adv/gateway_client.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ void batadv_gw_node_delete(struct batadv_priv *bat_priv,
3434
void batadv_gw_node_purge(struct batadv_priv *bat_priv);
3535
int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset);
3636
bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len);
37-
bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
38-
struct sk_buff *skb, struct ethhdr *ethhdr);
37+
bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, struct sk_buff *skb);
3938

4039
#endif /* _NET_BATMAN_ADV_GATEWAY_CLIENT_H_ */

net/batman-adv/soft-interface.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,9 @@ static int batadv_interface_tx(struct sk_buff *skb,
180180
if (batadv_bla_tx(bat_priv, skb, vid))
181181
goto dropped;
182182

183+
/* skb->data might have been reallocated by batadv_bla_tx() */
184+
ethhdr = (struct ethhdr *)skb->data;
185+
183186
/* Register the client MAC in the transtable */
184187
if (!is_multicast_ether_addr(ethhdr->h_source))
185188
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,
220223
default:
221224
break;
222225
}
226+
227+
/* reminder: ethhdr might have become unusable from here on
228+
* (batadv_gw_is_dhcp_target() might have reallocated skb data)
229+
*/
223230
}
224231

225232
/* ethernet packet should be broadcasted */
@@ -266,7 +273,7 @@ static int batadv_interface_tx(struct sk_buff *skb,
266273
/* unicast packet */
267274
} else {
268275
if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_OFF) {
269-
ret = batadv_gw_out_of_range(bat_priv, skb, ethhdr);
276+
ret = batadv_gw_out_of_range(bat_priv, skb);
270277
if (ret)
271278
goto dropped;
272279
}

net/batman-adv/unicast.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,9 @@ static bool batadv_unicast_push_and_fill_skb(struct sk_buff *skb, int hdr_size,
326326
* @skb: the skb containing the payload to encapsulate
327327
* @orig_node: the destination node
328328
*
329-
* Returns false if the payload could not be encapsulated or true otherwise
329+
* Returns false if the payload could not be encapsulated or true otherwise.
330+
*
331+
* This call might reallocate skb data.
330332
*/
331333
static bool batadv_unicast_prepare_skb(struct sk_buff *skb,
332334
struct batadv_orig_node *orig_node)
@@ -343,7 +345,9 @@ static bool batadv_unicast_prepare_skb(struct sk_buff *skb,
343345
* @orig_node: the destination node
344346
* @packet_subtype: the batman 4addr packet subtype to use
345347
*
346-
* Returns false if the payload could not be encapsulated or true otherwise
348+
* Returns false if the payload could not be encapsulated or true otherwise.
349+
*
350+
* This call might reallocate skb data.
347351
*/
348352
bool batadv_unicast_4addr_prepare_skb(struct batadv_priv *bat_priv,
349353
struct sk_buff *skb,
@@ -401,7 +405,7 @@ int batadv_unicast_generic_send_skb(struct batadv_priv *bat_priv,
401405
struct batadv_neigh_node *neigh_node;
402406
int data_len = skb->len;
403407
int ret = NET_RX_DROP;
404-
unsigned int dev_mtu;
408+
unsigned int dev_mtu, header_len;
405409

406410
/* get routing information */
407411
if (is_multicast_ether_addr(ethhdr->h_dest)) {
@@ -429,10 +433,12 @@ int batadv_unicast_generic_send_skb(struct batadv_priv *bat_priv,
429433
switch (packet_type) {
430434
case BATADV_UNICAST:
431435
batadv_unicast_prepare_skb(skb, orig_node);
436+
header_len = sizeof(struct batadv_unicast_packet);
432437
break;
433438
case BATADV_UNICAST_4ADDR:
434439
batadv_unicast_4addr_prepare_skb(bat_priv, skb, orig_node,
435440
packet_subtype);
441+
header_len = sizeof(struct batadv_unicast_4addr_packet);
436442
break;
437443
default:
438444
/* this function supports UNICAST and UNICAST_4ADDR only. It
@@ -441,6 +447,7 @@ int batadv_unicast_generic_send_skb(struct batadv_priv *bat_priv,
441447
goto out;
442448
}
443449

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

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

0 commit comments

Comments
 (0)