aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-12-07 20:00:57 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-07 20:00:57 -0500
commit1b3c393cd43f22ead8a6a2f839efc6df8ebd7465 (patch)
treecca25bcae0cc6172a616335041c1e54a33db451c
parent1afa471706963643ceeda7cbbe9c605a1e883d53 (diff)
parentc3c7c254b2e8cd99b0adf288c2a1bddacd7ba255 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking fixes from David Miller: "Two stragglers: 1) The new code that adds new flushing semantics to GRO can cause SKB pointer list corruption, manage the lists differently to avoid the OOPS. Fix from Eric Dumazet. 2) When TCP fast open does a retransmit of data in a SYN-ACK or similar, we update retransmit state that we shouldn't triggering a WARN_ON later. Fix from Yuchung Cheng." * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: net: gro: fix possible panic in skb_gro_receive() tcp: bug fix Fast Open client retransmission
-rw-r--r--include/linux/netdevice.h3
-rw-r--r--include/net/tcp.h1
-rw-r--r--net/core/dev.c2
-rw-r--r--net/core/skbuff.c6
-rw-r--r--net/ipv4/tcp_input.c6
-rw-r--r--net/ipv4/tcp_output.c15
6 files changed, 24 insertions, 9 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index f8eda0276f03..a848ffc327f4 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1488,6 +1488,9 @@ struct napi_gro_cb {
1488 1488
1489 /* Used in ipv6_gro_receive() */ 1489 /* Used in ipv6_gro_receive() */
1490 int proto; 1490 int proto;
1491
1492 /* used in skb_gro_receive() slow path */
1493 struct sk_buff *last;
1491}; 1494};
1492 1495
1493#define NAPI_GRO_CB(skb) ((struct napi_gro_cb *)(skb)->cb) 1496#define NAPI_GRO_CB(skb) ((struct napi_gro_cb *)(skb)->cb)
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 6feeccd83dd7..4af45e33105d 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -525,6 +525,7 @@ static inline __u32 cookie_v6_init_sequence(struct sock *sk,
525extern void __tcp_push_pending_frames(struct sock *sk, unsigned int cur_mss, 525extern void __tcp_push_pending_frames(struct sock *sk, unsigned int cur_mss,
526 int nonagle); 526 int nonagle);
527extern bool tcp_may_send_now(struct sock *sk); 527extern bool tcp_may_send_now(struct sock *sk);
528extern int __tcp_retransmit_skb(struct sock *, struct sk_buff *);
528extern int tcp_retransmit_skb(struct sock *, struct sk_buff *); 529extern int tcp_retransmit_skb(struct sock *, struct sk_buff *);
529extern void tcp_retransmit_timer(struct sock *sk); 530extern void tcp_retransmit_timer(struct sock *sk);
530extern void tcp_xmit_retransmit_queue(struct sock *); 531extern void tcp_xmit_retransmit_queue(struct sock *);
diff --git a/net/core/dev.c b/net/core/dev.c
index c0946cb2b354..e5942bf45a6d 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3451,6 +3451,8 @@ static int napi_gro_complete(struct sk_buff *skb)
3451 struct list_head *head = &ptype_base[ntohs(type) & PTYPE_HASH_MASK]; 3451 struct list_head *head = &ptype_base[ntohs(type) & PTYPE_HASH_MASK];
3452 int err = -ENOENT; 3452 int err = -ENOENT;
3453 3453
3454 BUILD_BUG_ON(sizeof(struct napi_gro_cb) > sizeof(skb->cb));
3455
3454 if (NAPI_GRO_CB(skb)->count == 1) { 3456 if (NAPI_GRO_CB(skb)->count == 1) {
3455 skb_shinfo(skb)->gso_size = 0; 3457 skb_shinfo(skb)->gso_size = 0;
3456 goto out; 3458 goto out;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 4007c1437fda..3f0636cd76cd 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -3004,7 +3004,7 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
3004 skb_shinfo(nskb)->gso_size = pinfo->gso_size; 3004 skb_shinfo(nskb)->gso_size = pinfo->gso_size;
3005 pinfo->gso_size = 0; 3005 pinfo->gso_size = 0;
3006 skb_header_release(p); 3006 skb_header_release(p);
3007 nskb->prev = p; 3007 NAPI_GRO_CB(nskb)->last = p;
3008 3008
3009 nskb->data_len += p->len; 3009 nskb->data_len += p->len;
3010 nskb->truesize += p->truesize; 3010 nskb->truesize += p->truesize;
@@ -3030,8 +3030,8 @@ merge:
3030 3030
3031 __skb_pull(skb, offset); 3031 __skb_pull(skb, offset);
3032 3032
3033 p->prev->next = skb; 3033 NAPI_GRO_CB(p)->last->next = skb;
3034 p->prev = skb; 3034 NAPI_GRO_CB(p)->last = skb;
3035 skb_header_release(skb); 3035 skb_header_release(skb);
3036 3036
3037done: 3037done:
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 609ff98aeb47..181fc8234a52 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -5645,7 +5645,11 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack,
5645 tcp_fastopen_cache_set(sk, mss, cookie, syn_drop); 5645 tcp_fastopen_cache_set(sk, mss, cookie, syn_drop);
5646 5646
5647 if (data) { /* Retransmit unacked data in SYN */ 5647 if (data) { /* Retransmit unacked data in SYN */
5648 tcp_retransmit_skb(sk, data); 5648 tcp_for_write_queue_from(data, sk) {
5649 if (data == tcp_send_head(sk) ||
5650 __tcp_retransmit_skb(sk, data))
5651 break;
5652 }
5649 tcp_rearm_rto(sk); 5653 tcp_rearm_rto(sk);
5650 return true; 5654 return true;
5651 } 5655 }
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 2798706cb063..948ac275b9b5 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -2309,12 +2309,11 @@ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *to,
2309 * state updates are done by the caller. Returns non-zero if an 2309 * state updates are done by the caller. Returns non-zero if an
2310 * error occurred which prevented the send. 2310 * error occurred which prevented the send.
2311 */ 2311 */
2312int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) 2312int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
2313{ 2313{
2314 struct tcp_sock *tp = tcp_sk(sk); 2314 struct tcp_sock *tp = tcp_sk(sk);
2315 struct inet_connection_sock *icsk = inet_csk(sk); 2315 struct inet_connection_sock *icsk = inet_csk(sk);
2316 unsigned int cur_mss; 2316 unsigned int cur_mss;
2317 int err;
2318 2317
2319 /* Inconslusive MTU probe */ 2318 /* Inconslusive MTU probe */
2320 if (icsk->icsk_mtup.probe_size) { 2319 if (icsk->icsk_mtup.probe_size) {
@@ -2387,11 +2386,17 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
2387 if (unlikely(NET_IP_ALIGN && ((unsigned long)skb->data & 3))) { 2386 if (unlikely(NET_IP_ALIGN && ((unsigned long)skb->data & 3))) {
2388 struct sk_buff *nskb = __pskb_copy(skb, MAX_TCP_HEADER, 2387 struct sk_buff *nskb = __pskb_copy(skb, MAX_TCP_HEADER,
2389 GFP_ATOMIC); 2388 GFP_ATOMIC);
2390 err = nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) : 2389 return nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) :
2391 -ENOBUFS; 2390 -ENOBUFS;
2392 } else { 2391 } else {
2393 err = tcp_transmit_skb(sk, skb, 1, GFP_ATOMIC); 2392 return tcp_transmit_skb(sk, skb, 1, GFP_ATOMIC);
2394 } 2393 }
2394}
2395
2396int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
2397{
2398 struct tcp_sock *tp = tcp_sk(sk);
2399 int err = __tcp_retransmit_skb(sk, skb);
2395 2400
2396 if (err == 0) { 2401 if (err == 0) {
2397 /* Update global TCP statistics. */ 2402 /* Update global TCP statistics. */