The following commit has been merged in the merge/master branch: commit ada79851d379271e7b22d638ddcc3f17d8baa9d9 Author: Sven Eckelmann sven@narfation.org Date: Sun Feb 6 23:26:43 2011 +0000
batman-adv: Linearize fragment packets before merge
We access the data inside the skbs of two fragments directly using memmove during the merge. The data of the skb could span over multiple skb pages. An direct access without knowledge about the pages would lead to an invalid memory access.
Signed-off-by: Sven Eckelmann sven@narfation.org
diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c index cbf022c..d8d079f 100644 --- a/net/batman-adv/unicast.c +++ b/net/batman-adv/unicast.c @@ -40,7 +40,7 @@ static struct sk_buff *frag_merge_packet(struct list_head *head, struct sk_buff *tmp_skb; struct unicast_packet *unicast_packet; int hdr_len = sizeof(struct unicast_packet), - uni_diff = sizeof(struct unicast_frag_packet) - hdr_len; + uni_diff = sizeof(struct unicast_frag_packet) - hdr_len;
/* set skb to the first part and tmp_skb to the second part */ if (up->flags & UNI_FRAG_HEAD) { @@ -50,12 +50,12 @@ static struct sk_buff *frag_merge_packet(struct list_head *head, skb = tfp->skb; }
+ if (skb_linearize(skb) < 0 || skb_linearize(tmp_skb) < 0) + goto err; + skb_pull(tmp_skb, sizeof(struct unicast_frag_packet)); - if (pskb_expand_head(skb, 0, tmp_skb->len, GFP_ATOMIC) < 0) { - /* free buffered skb, skb will be freed later */ - kfree_skb(tfp->skb); - return NULL; - } + if (pskb_expand_head(skb, 0, tmp_skb->len, GFP_ATOMIC) < 0) + goto err;
/* move free entry to end */ tfp->skb = NULL; @@ -70,6 +70,11 @@ static struct sk_buff *frag_merge_packet(struct list_head *head, unicast_packet->packet_type = BAT_UNICAST;
return skb; + +err: + /* free buffered skb, skb will be freed later */ + kfree_skb(tfp->skb); + return NULL; }
static void frag_create_entry(struct list_head *head, struct sk_buff *skb)