aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/batman-adv
diff options
context:
space:
mode:
authorSven Eckelmann <sven.eckelmann@gmx.de>2010-05-07 15:47:07 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-05-11 16:42:38 -0400
commitf347b8736f176681fbfc666bf00165125a3274a5 (patch)
tree1aca9e9ddf9b3b32843b2e06815b9f35cd2a04cd /drivers/staging/batman-adv
parentadaaa0c6ab89e82684389b80002bce893179cf2c (diff)
Staging: batman-adv: Clone shared bat packets before modifying them
"tcpdump" and "batctl td" will receive packets with a wrong sequence number on systems with a different endianess than network byte order. This happens due to the reordering of bytes in the function which handles aggregated bat packets. The function which receives the bat packets must ensure that these buffers aren't shared with anything else before that function tries to write into it. Otherwise it has to copy the buffers so it is save again to change them. Reported-by: Kevin Steen <batman@kevinsteen.net> Signed-off-by: Sven Eckelmann <sven.eckelmann@gmx.de> Signed-off-by: Marek Lindner <lindner_marek@yahoo.de> Signed-off-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/batman-adv')
-rw-r--r--drivers/staging/batman-adv/routing.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c
index d89048beebe..39dd093d7f2 100644
--- a/drivers/staging/batman-adv/routing.c
+++ b/drivers/staging/batman-adv/routing.c
@@ -549,6 +549,7 @@ int recv_bat_packet(struct sk_buff *skb,
549{ 549{
550 struct ethhdr *ethhdr; 550 struct ethhdr *ethhdr;
551 unsigned long flags; 551 unsigned long flags;
552 struct sk_buff *skb_old;
552 553
553 /* drop packet if it has not necessary minimum size */ 554 /* drop packet if it has not necessary minimum size */
554 if (skb_headlen(skb) < sizeof(struct batman_packet)) 555 if (skb_headlen(skb) < sizeof(struct batman_packet))
@@ -564,12 +565,19 @@ int recv_bat_packet(struct sk_buff *skb,
564 if (is_bcast(ethhdr->h_source)) 565 if (is_bcast(ethhdr->h_source))
565 return NET_RX_DROP; 566 return NET_RX_DROP;
566 567
567 spin_lock_irqsave(&orig_hash_lock, flags);
568 /* TODO: we use headlen instead of "length", because 568 /* TODO: we use headlen instead of "length", because
569 * only this data is paged in. */ 569 * only this data is paged in. */
570 /* TODO: is another skb_copy needed here? there will be 570
571 * written on the data, but nobody (?) should further use 571 /* create a copy of the skb, if needed, to modify it. */
572 * this data */ 572 if (!skb_clone_writable(skb, skb_headlen(skb))) {
573 skb_old = skb;
574 skb = skb_copy(skb, GFP_ATOMIC);
575 if (!skb)
576 return NET_RX_DROP;
577 kfree_skb(skb_old);
578 }
579
580 spin_lock_irqsave(&orig_hash_lock, flags);
573 receive_aggr_bat_packet(ethhdr, 581 receive_aggr_bat_packet(ethhdr,
574 skb->data, 582 skb->data,
575 skb_headlen(skb), 583 skb_headlen(skb),