commit 68c3316311 ("v4 GRE: Add TCP segmentation offload for GRE")
added a possible skb leak, because it frees only the head of segment
list, in case a skb_linearize() call fails.

This patch adds a kfree_skb_list() helper to fix the bug.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Pravin B Shelar <pshelar@nicira.com>
Cc: Daniel Borkmann <dborkman@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Eric Dumazet 2013-06-24 06:26:00 -07:00 коммит произвёл David S. Miller
Родитель 2b7a5db060
Коммит bd8a7036c0
3 изменённых файлов: 14 добавлений и 9 удалений

Просмотреть файл

@ -627,6 +627,7 @@ static inline struct rtable *skb_rtable(const struct sk_buff *skb)
} }
extern void kfree_skb(struct sk_buff *skb); extern void kfree_skb(struct sk_buff *skb);
extern void kfree_skb_list(struct sk_buff *segs);
extern void skb_tx_error(struct sk_buff *skb); extern void skb_tx_error(struct sk_buff *skb);
extern void consume_skb(struct sk_buff *skb); extern void consume_skb(struct sk_buff *skb);
extern void __kfree_skb(struct sk_buff *skb); extern void __kfree_skb(struct sk_buff *skb);

Просмотреть файл

@ -483,15 +483,8 @@ EXPORT_SYMBOL(skb_add_rx_frag);
static void skb_drop_list(struct sk_buff **listp) static void skb_drop_list(struct sk_buff **listp)
{ {
struct sk_buff *list = *listp; kfree_skb_list(*listp);
*listp = NULL; *listp = NULL;
do {
struct sk_buff *this = list;
list = list->next;
kfree_skb(this);
} while (list);
} }
static inline void skb_drop_fraglist(struct sk_buff *skb) static inline void skb_drop_fraglist(struct sk_buff *skb)
@ -651,6 +644,17 @@ void kfree_skb(struct sk_buff *skb)
} }
EXPORT_SYMBOL(kfree_skb); EXPORT_SYMBOL(kfree_skb);
void kfree_skb_list(struct sk_buff *segs)
{
while (segs) {
struct sk_buff *next = segs->next;
kfree_skb(segs);
segs = next;
}
}
EXPORT_SYMBOL(kfree_skb_list);
/** /**
* skb_tx_error - report an sk_buff xmit error * skb_tx_error - report an sk_buff xmit error
* @skb: buffer that triggered an error * @skb: buffer that triggered an error

Просмотреть файл

@ -178,7 +178,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
err = __skb_linearize(skb); err = __skb_linearize(skb);
if (err) { if (err) {
kfree_skb(segs); kfree_skb_list(segs);
segs = ERR_PTR(err); segs = ERR_PTR(err);
goto out; goto out;
} }