diff options
Diffstat (limited to 'net/ipv4/tcp_ipv4.c')
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 11 |
1 files changed, 9 insertions, 2 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 277d71239d75..3979939804b7 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -1774,6 +1774,7 @@ static void tcp_v4_fill_cb(struct sk_buff *skb, const struct iphdr *iph, | |||
1774 | int tcp_v4_rcv(struct sk_buff *skb) | 1774 | int tcp_v4_rcv(struct sk_buff *skb) |
1775 | { | 1775 | { |
1776 | struct net *net = dev_net(skb->dev); | 1776 | struct net *net = dev_net(skb->dev); |
1777 | struct sk_buff *skb_to_free; | ||
1777 | int sdif = inet_sdif(skb); | 1778 | int sdif = inet_sdif(skb); |
1778 | const struct iphdr *iph; | 1779 | const struct iphdr *iph; |
1779 | const struct tcphdr *th; | 1780 | const struct tcphdr *th; |
@@ -1905,11 +1906,17 @@ process: | |||
1905 | tcp_segs_in(tcp_sk(sk), skb); | 1906 | tcp_segs_in(tcp_sk(sk), skb); |
1906 | ret = 0; | 1907 | ret = 0; |
1907 | if (!sock_owned_by_user(sk)) { | 1908 | if (!sock_owned_by_user(sk)) { |
1909 | skb_to_free = sk->sk_rx_skb_cache; | ||
1910 | sk->sk_rx_skb_cache = NULL; | ||
1908 | ret = tcp_v4_do_rcv(sk, skb); | 1911 | ret = tcp_v4_do_rcv(sk, skb); |
1909 | } else if (tcp_add_backlog(sk, skb)) { | 1912 | } else { |
1910 | goto discard_and_relse; | 1913 | if (tcp_add_backlog(sk, skb)) |
1914 | goto discard_and_relse; | ||
1915 | skb_to_free = NULL; | ||
1911 | } | 1916 | } |
1912 | bh_unlock_sock(sk); | 1917 | bh_unlock_sock(sk); |
1918 | if (skb_to_free) | ||
1919 | __kfree_skb(skb_to_free); | ||
1913 | 1920 | ||
1914 | put_and_return: | 1921 | put_and_return: |
1915 | if (refcounted) | 1922 | if (refcounted) |