This is a note to let you know that I've just added the patch titled
tcp: make sure skb is not shared before using skb_get()
to the 3.19-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
tcp-make-sure-skb-is-not-shared-before-using-skb_get.patch
and it can be found in the queue-3.19 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree,
please let <[email protected]> know about it.
>From foo@baz Wed Mar 11 11:44:33 CET 2015
From: Eric Dumazet <[email protected]>
Date: Fri, 13 Feb 2015 04:47:12 -0800
Subject: tcp: make sure skb is not shared before using skb_get()
From: Eric Dumazet <[email protected]>
[ Upstream commit ba34e6d9d346fe4e05d7e417b9edf5140772d34c ]
IPv6 can keep a copy of SYN message using skb_get() in
tcp_v6_conn_request() so that caller wont free the skb when calling
kfree_skb() later.
Therefore TCP fast open has to clone the skb it is queuing in
child->sk_receive_queue, as all skbs consumed from receive_queue are
freed using __kfree_skb() (ie assuming skb->users == 1)
Signed-off-by: Eric Dumazet <[email protected]>
Signed-off-by: Yuchung Cheng <[email protected]>
Fixes: 5b7ed0892f2af ("tcp: move fastopen functions to tcp_fastopen.c")
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ipv4/tcp_fastopen.c | 32 ++++++++++++++++++++++++--------
1 file changed, 24 insertions(+), 8 deletions(-)
--- a/net/ipv4/tcp_fastopen.c
+++ b/net/ipv4/tcp_fastopen.c
@@ -134,6 +134,7 @@ static bool tcp_fastopen_create_child(st
struct tcp_sock *tp;
struct request_sock_queue *queue = &inet_csk(sk)->icsk_accept_queue;
struct sock *child;
+ u32 end_seq;
req->num_retrans = 0;
req->num_timeout = 0;
@@ -185,20 +186,35 @@ static bool tcp_fastopen_create_child(st
/* Queue the data carried in the SYN packet. We need to first
* bump skb's refcnt because the caller will attempt to free it.
+ * Note that IPv6 might also have used skb_get() trick
+ * in tcp_v6_conn_request() to keep this SYN around (treq->pktopts)
+ * So we need to eventually get a clone of the packet,
+ * before inserting it in sk_receive_queue.
*
* XXX (TFO) - we honor a zero-payload TFO request for now,
* (any reason not to?) but no need to queue the skb since
* there is no data. How about SYN+FIN?
*/
- if (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq + 1) {
- skb = skb_get(skb);
- skb_dst_drop(skb);
- __skb_pull(skb, tcp_hdr(skb)->doff * 4);
- skb_set_owner_r(skb, child);
- __skb_queue_tail(&child->sk_receive_queue, skb);
- tp->syn_data_acked = 1;
+ end_seq = TCP_SKB_CB(skb)->end_seq;
+ if (end_seq != TCP_SKB_CB(skb)->seq + 1) {
+ struct sk_buff *skb2;
+
+ if (unlikely(skb_shared(skb)))
+ skb2 = skb_clone(skb, GFP_ATOMIC);
+ else
+ skb2 = skb_get(skb);
+
+ if (likely(skb2)) {
+ skb_dst_drop(skb2);
+ __skb_pull(skb2, tcp_hdrlen(skb));
+ skb_set_owner_r(skb2, child);
+ __skb_queue_tail(&child->sk_receive_queue, skb2);
+ tp->syn_data_acked = 1;
+ } else {
+ end_seq = TCP_SKB_CB(skb)->seq + 1;
+ }
}
- tcp_rsk(req)->rcv_nxt = tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
+ tcp_rsk(req)->rcv_nxt = tp->rcv_nxt = end_seq;
sk->sk_data_ready(sk);
bh_unlock_sock(child);
sock_put(child);
Patches currently in stable-queue which might be from [email protected] are
queue-3.19/net-pktgen-disable-xmit_clone-on-virtual-devices.patch
queue-3.19/net-do-not-use-rcu-in-rtnl_dump_ifinfo.patch
queue-3.19/flowcache-fix-kernel-panic-in-flow_cache_flush_task.patch
queue-3.19/tcp-make-sure-skb-is-not-shared-before-using-skb_get.patch
queue-3.19/sock-sock_dequeue_err_skb-needs-hard-irq-safety.patch
queue-3.19/macvtap-make-sure-neighbour-code-can-push-ethernet-header.patch
queue-3.19/ipv4-ip_check_defrag-should-correctly-check-return-value-of-skb_copy_bits.patch
--
To unsubscribe from this list: send the line "unsubscribe stable" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html