Skip to content

Commit

Permalink
Staging: batman-adv: Provide full headers and packets as linear skb
Browse files Browse the repository at this point in the history
We must ensure that all interesting data is linear and not paged out to
access all information in a header or a full batman-adv related packet.
Otherwise we may drop packets which have non-linear headers but which
hold valid data.

This doesn't affect non-linear skbs which have all headers in a linear
head unless we must process the whole packet like in ogms or vis
packets.

Signed-off-by: Sven Eckelmann <sven.eckelmann@gmx.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Sven Eckelmann authored and Greg Kroah-Hartman committed Sep 5, 2010
1 parent aedbffc commit bf3264f
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 9 deletions.
2 changes: 1 addition & 1 deletion drivers/staging/batman-adv/hard-interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
goto err_free;

/* packet should hold at least type and version */
if (unlikely(skb_headlen(skb) < 2))
if (unlikely(!pskb_may_pull(skb, 2)))
goto err_free;

/* expect a valid ethernet header here. */
Expand Down
22 changes: 14 additions & 8 deletions drivers/staging/batman-adv/routing.c
Original file line number Diff line number Diff line change
Expand Up @@ -744,7 +744,7 @@ int recv_bat_packet(struct sk_buff *skb,
unsigned long flags;

/* drop packet if it has not necessary minimum size */
if (skb_headlen(skb) < sizeof(struct batman_packet))
if (unlikely(!pskb_may_pull(skb, sizeof(struct batman_packet))))
return NET_RX_DROP;

ethhdr = (struct ethhdr *)skb_mac_header(skb);
Expand All @@ -761,6 +761,10 @@ int recv_bat_packet(struct sk_buff *skb,
if (skb_cow(skb, 0) < 0)
return NET_RX_DROP;

/* keep skb linear */
if (skb_linearize(skb) < 0)
return NET_RX_DROP;

ethhdr = (struct ethhdr *)skb_mac_header(skb);

spin_lock_irqsave(&orig_hash_lock, flags);
Expand Down Expand Up @@ -914,11 +918,11 @@ int recv_icmp_packet(struct sk_buff *skb)
/**
* we truncate all incoming icmp packets if they don't match our size
*/
if (skb_headlen(skb) >= sizeof(struct icmp_packet_rr))
if (skb->len >= sizeof(struct icmp_packet_rr))
hdr_size = sizeof(struct icmp_packet_rr);

/* drop packet if it has not necessary minimum size */
if (skb_headlen(skb) < hdr_size)
if (unlikely(!pskb_may_pull(skb, hdr_size)))
return NET_RX_DROP;

ethhdr = (struct ethhdr *)skb_mac_header(skb);
Expand Down Expand Up @@ -1087,7 +1091,7 @@ static int check_unicast_packet(struct sk_buff *skb, int hdr_size)
struct ethhdr *ethhdr;

/* drop packet if it has not necessary minimum size */
if (skb_headlen(skb) < hdr_size)
if (unlikely(!pskb_may_pull(skb, hdr_size)))
return -1;

ethhdr = (struct ethhdr *) skb_mac_header(skb);
Expand Down Expand Up @@ -1247,7 +1251,7 @@ int recv_bcast_packet(struct sk_buff *skb)
unsigned long flags;

/* drop packet if it has not necessary minimum size */
if (skb_headlen(skb) < hdr_size)
if (unlikely(!pskb_may_pull(skb, hdr_size)))
return NET_RX_DROP;

ethhdr = (struct ethhdr *)skb_mac_header(skb);
Expand Down Expand Up @@ -1320,7 +1324,11 @@ int recv_vis_packet(struct sk_buff *skb)
struct bat_priv *bat_priv;
int hdr_size = sizeof(struct vis_packet);

if (skb_headlen(skb) < hdr_size)
/* keep skb linear */
if (skb_linearize(skb) < 0)
return NET_RX_DROP;

if (unlikely(!pskb_may_pull(skb, hdr_size)))
return NET_RX_DROP;

vis_packet = (struct vis_packet *) skb->data;
Expand All @@ -1342,13 +1350,11 @@ int recv_vis_packet(struct sk_buff *skb)

switch (vis_packet->vis_type) {
case VIS_TYPE_SERVER_SYNC:
/* TODO: handle fragmented skbs properly */
receive_server_sync_packet(bat_priv, vis_packet,
skb_headlen(skb));
break;

case VIS_TYPE_CLIENT_UPDATE:
/* TODO: handle fragmented skbs properly */
receive_client_update_packet(bat_priv, vis_packet,
skb_headlen(skb));
break;
Expand Down

0 comments on commit bf3264f

Please sign in to comment.