diff options
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 983ad7a75102..77d723bbe050 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -1436,6 +1436,7 @@ static void tcp_v6_fill_cb(struct sk_buff *skb, const struct ipv6hdr *hdr, | |||
1436 | 1436 | ||
1437 | static int tcp_v6_rcv(struct sk_buff *skb) | 1437 | static int tcp_v6_rcv(struct sk_buff *skb) |
1438 | { | 1438 | { |
1439 | struct sk_buff *skb_to_free; | ||
1439 | int sdif = inet6_sdif(skb); | 1440 | int sdif = inet6_sdif(skb); |
1440 | const struct tcphdr *th; | 1441 | const struct tcphdr *th; |
1441 | const struct ipv6hdr *hdr; | 1442 | const struct ipv6hdr *hdr; |
@@ -1562,12 +1563,17 @@ process: | |||
1562 | tcp_segs_in(tcp_sk(sk), skb); | 1563 | tcp_segs_in(tcp_sk(sk), skb); |
1563 | ret = 0; | 1564 | ret = 0; |
1564 | if (!sock_owned_by_user(sk)) { | 1565 | if (!sock_owned_by_user(sk)) { |
1566 | skb_to_free = sk->sk_rx_skb_cache; | ||
1567 | sk->sk_rx_skb_cache = NULL; | ||
1565 | ret = tcp_v6_do_rcv(sk, skb); | 1568 | ret = tcp_v6_do_rcv(sk, skb); |
1566 | } else if (tcp_add_backlog(sk, skb)) { | 1569 | } else { |
1567 | goto discard_and_relse; | 1570 | if (tcp_add_backlog(sk, skb)) |
1571 | goto discard_and_relse; | ||
1572 | skb_to_free = NULL; | ||
1568 | } | 1573 | } |
1569 | bh_unlock_sock(sk); | 1574 | bh_unlock_sock(sk); |
1570 | 1575 | if (skb_to_free) | |
1576 | __kfree_skb(skb_to_free); | ||
1571 | put_and_return: | 1577 | put_and_return: |
1572 | if (refcounted) | 1578 | if (refcounted) |
1573 | sock_put(sk); | 1579 | sock_put(sk); |