]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/staging/batman-adv/routing.c
Staging: batman-adv: Clone shared bat packets before modifying them
[net-next-2.6.git] / drivers / staging / batman-adv / routing.c
index d89048beebe16b7727e9de46cf9871cdedaea107..39dd093d7f2d5cd81bc79a81af705212a70038e5 100644 (file)
@@ -549,6 +549,7 @@ int recv_bat_packet(struct sk_buff *skb,
 {
        struct ethhdr *ethhdr;
        unsigned long flags;
+       struct sk_buff *skb_old;
 
        /* drop packet if it has not necessary minimum size */
        if (skb_headlen(skb) < sizeof(struct batman_packet))
@@ -564,12 +565,19 @@ int recv_bat_packet(struct sk_buff *skb,
        if (is_bcast(ethhdr->h_source))
                return NET_RX_DROP;
 
-       spin_lock_irqsave(&orig_hash_lock, flags);
        /* TODO: we use headlen instead of "length", because
         * only this data is paged in. */
-       /* TODO: is another skb_copy needed here? there will be
-        * written on the data, but nobody (?) should further use
-        * this data */
+
+       /* create a copy of the skb, if needed, to modify it. */
+       if (!skb_clone_writable(skb, skb_headlen(skb))) {
+               skb_old = skb;
+               skb = skb_copy(skb, GFP_ATOMIC);
+               if (!skb)
+                       return NET_RX_DROP;
+               kfree_skb(skb_old);
+       }
+
+       spin_lock_irqsave(&orig_hash_lock, flags);
        receive_aggr_bat_packet(ethhdr,
                                skb->data,
                                skb_headlen(skb),