gre: fix a possible skb leak
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:
Родитель
2b7a5db060
Коммит
bd8a7036c0
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче