diff options
author | Sven Eckelmann <sven.eckelmann@gmx.de> | 2010-09-04 19:58:33 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-09-05 03:29:48 -0400 |
commit | bf3264f6d1039e68ec9881447808327c0260ae61 (patch) | |
tree | 0e32f535634ac1e60f6eb9f25ea914ea1d9c4d0e | |
parent | aedbffc7774574de74563f350b363cbfb52984fd (diff) |
Staging: batman-adv: Provide full headers and packets as linear skb
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>
-rw-r--r-- | drivers/staging/batman-adv/hard-interface.c | 2 | ||||
-rw-r--r-- | drivers/staging/batman-adv/routing.c | 22 |
2 files changed, 15 insertions, 9 deletions
diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c index f33c73f72d5..c1863d240f7 100644 --- a/drivers/staging/batman-adv/hard-interface.c +++ b/drivers/staging/batman-adv/hard-interface.c | |||
@@ -486,7 +486,7 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, | |||
486 | goto err_free; | 486 | goto err_free; |
487 | 487 | ||
488 | /* packet should hold at least type and version */ | 488 | /* packet should hold at least type and version */ |
489 | if (unlikely(skb_headlen(skb) < 2)) | 489 | if (unlikely(!pskb_may_pull(skb, 2))) |
490 | goto err_free; | 490 | goto err_free; |
491 | 491 | ||
492 | /* expect a valid ethernet header here. */ | 492 | /* expect a valid ethernet header here. */ |
diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c index 7e993a25349..6009adc80b8 100644 --- a/drivers/staging/batman-adv/routing.c +++ b/drivers/staging/batman-adv/routing.c | |||
@@ -744,7 +744,7 @@ int recv_bat_packet(struct sk_buff *skb, | |||
744 | unsigned long flags; | 744 | unsigned long flags; |
745 | 745 | ||
746 | /* drop packet if it has not necessary minimum size */ | 746 | /* drop packet if it has not necessary minimum size */ |
747 | if (skb_headlen(skb) < sizeof(struct batman_packet)) | 747 | if (unlikely(!pskb_may_pull(skb, sizeof(struct batman_packet)))) |
748 | return NET_RX_DROP; | 748 | return NET_RX_DROP; |
749 | 749 | ||
750 | ethhdr = (struct ethhdr *)skb_mac_header(skb); | 750 | ethhdr = (struct ethhdr *)skb_mac_header(skb); |
@@ -761,6 +761,10 @@ int recv_bat_packet(struct sk_buff *skb, | |||
761 | if (skb_cow(skb, 0) < 0) | 761 | if (skb_cow(skb, 0) < 0) |
762 | return NET_RX_DROP; | 762 | return NET_RX_DROP; |
763 | 763 | ||
764 | /* keep skb linear */ | ||
765 | if (skb_linearize(skb) < 0) | ||
766 | return NET_RX_DROP; | ||
767 | |||
764 | ethhdr = (struct ethhdr *)skb_mac_header(skb); | 768 | ethhdr = (struct ethhdr *)skb_mac_header(skb); |
765 | 769 | ||
766 | spin_lock_irqsave(&orig_hash_lock, flags); | 770 | spin_lock_irqsave(&orig_hash_lock, flags); |
@@ -914,11 +918,11 @@ int recv_icmp_packet(struct sk_buff *skb) | |||
914 | /** | 918 | /** |
915 | * we truncate all incoming icmp packets if they don't match our size | 919 | * we truncate all incoming icmp packets if they don't match our size |
916 | */ | 920 | */ |
917 | if (skb_headlen(skb) >= sizeof(struct icmp_packet_rr)) | 921 | if (skb->len >= sizeof(struct icmp_packet_rr)) |
918 | hdr_size = sizeof(struct icmp_packet_rr); | 922 | hdr_size = sizeof(struct icmp_packet_rr); |
919 | 923 | ||
920 | /* drop packet if it has not necessary minimum size */ | 924 | /* drop packet if it has not necessary minimum size */ |
921 | if (skb_headlen(skb) < hdr_size) | 925 | if (unlikely(!pskb_may_pull(skb, hdr_size))) |
922 | return NET_RX_DROP; | 926 | return NET_RX_DROP; |
923 | 927 | ||
924 | ethhdr = (struct ethhdr *)skb_mac_header(skb); | 928 | ethhdr = (struct ethhdr *)skb_mac_header(skb); |
@@ -1087,7 +1091,7 @@ static int check_unicast_packet(struct sk_buff *skb, int hdr_size) | |||
1087 | struct ethhdr *ethhdr; | 1091 | struct ethhdr *ethhdr; |
1088 | 1092 | ||
1089 | /* drop packet if it has not necessary minimum size */ | 1093 | /* drop packet if it has not necessary minimum size */ |
1090 | if (skb_headlen(skb) < hdr_size) | 1094 | if (unlikely(!pskb_may_pull(skb, hdr_size))) |
1091 | return -1; | 1095 | return -1; |
1092 | 1096 | ||
1093 | ethhdr = (struct ethhdr *) skb_mac_header(skb); | 1097 | ethhdr = (struct ethhdr *) skb_mac_header(skb); |
@@ -1247,7 +1251,7 @@ int recv_bcast_packet(struct sk_buff *skb) | |||
1247 | unsigned long flags; | 1251 | unsigned long flags; |
1248 | 1252 | ||
1249 | /* drop packet if it has not necessary minimum size */ | 1253 | /* drop packet if it has not necessary minimum size */ |
1250 | if (skb_headlen(skb) < hdr_size) | 1254 | if (unlikely(!pskb_may_pull(skb, hdr_size))) |
1251 | return NET_RX_DROP; | 1255 | return NET_RX_DROP; |
1252 | 1256 | ||
1253 | ethhdr = (struct ethhdr *)skb_mac_header(skb); | 1257 | ethhdr = (struct ethhdr *)skb_mac_header(skb); |
@@ -1320,7 +1324,11 @@ int recv_vis_packet(struct sk_buff *skb) | |||
1320 | struct bat_priv *bat_priv; | 1324 | struct bat_priv *bat_priv; |
1321 | int hdr_size = sizeof(struct vis_packet); | 1325 | int hdr_size = sizeof(struct vis_packet); |
1322 | 1326 | ||
1323 | if (skb_headlen(skb) < hdr_size) | 1327 | /* keep skb linear */ |
1328 | if (skb_linearize(skb) < 0) | ||
1329 | return NET_RX_DROP; | ||
1330 | |||
1331 | if (unlikely(!pskb_may_pull(skb, hdr_size))) | ||
1324 | return NET_RX_DROP; | 1332 | return NET_RX_DROP; |
1325 | 1333 | ||
1326 | vis_packet = (struct vis_packet *) skb->data; | 1334 | vis_packet = (struct vis_packet *) skb->data; |
@@ -1342,13 +1350,11 @@ int recv_vis_packet(struct sk_buff *skb) | |||
1342 | 1350 | ||
1343 | switch (vis_packet->vis_type) { | 1351 | switch (vis_packet->vis_type) { |
1344 | case VIS_TYPE_SERVER_SYNC: | 1352 | case VIS_TYPE_SERVER_SYNC: |
1345 | /* TODO: handle fragmented skbs properly */ | ||
1346 | receive_server_sync_packet(bat_priv, vis_packet, | 1353 | receive_server_sync_packet(bat_priv, vis_packet, |
1347 | skb_headlen(skb)); | 1354 | skb_headlen(skb)); |
1348 | break; | 1355 | break; |
1349 | 1356 | ||
1350 | case VIS_TYPE_CLIENT_UPDATE: | 1357 | case VIS_TYPE_CLIENT_UPDATE: |
1351 | /* TODO: handle fragmented skbs properly */ | ||
1352 | receive_client_update_packet(bat_priv, vis_packet, | 1358 | receive_client_update_packet(bat_priv, vis_packet, |
1353 | skb_headlen(skb)); | 1359 | skb_headlen(skb)); |
1354 | break; | 1360 | break; |