Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Linus Torvalds committed Dec 8, 2012
2 parents 1afa471 + c3c7c25 commit 1b3c393
Show file tree
Hide file tree
Showing 6 changed files with 24 additions and 9 deletions.
3 changes: 3 additions & 0 deletions include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -1488,6 +1488,9 @@ struct napi_gro_cb {

/* Used in ipv6_gro_receive() */
int proto;

/* used in skb_gro_receive() slow path */
struct sk_buff *last;
};

#define NAPI_GRO_CB(skb) ((struct napi_gro_cb *)(skb)->cb)
Expand Down
1 change: 1 addition & 0 deletions include/net/tcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,7 @@ static inline __u32 cookie_v6_init_sequence(struct sock *sk,
extern void __tcp_push_pending_frames(struct sock *sk, unsigned int cur_mss,
int nonagle);
extern bool tcp_may_send_now(struct sock *sk);
extern int __tcp_retransmit_skb(struct sock *, struct sk_buff *);
extern int tcp_retransmit_skb(struct sock *, struct sk_buff *);
extern void tcp_retransmit_timer(struct sock *sk);
extern void tcp_xmit_retransmit_queue(struct sock *);
Expand Down
2 changes: 2 additions & 0 deletions net/core/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -3451,6 +3451,8 @@ static int napi_gro_complete(struct sk_buff *skb)
struct list_head *head = &ptype_base[ntohs(type) & PTYPE_HASH_MASK];
int err = -ENOENT;

BUILD_BUG_ON(sizeof(struct napi_gro_cb) > sizeof(skb->cb));

if (NAPI_GRO_CB(skb)->count == 1) {
skb_shinfo(skb)->gso_size = 0;
goto out;
Expand Down
6 changes: 3 additions & 3 deletions net/core/skbuff.c
Original file line number Diff line number Diff line change
Expand Up @@ -3004,7 +3004,7 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
skb_shinfo(nskb)->gso_size = pinfo->gso_size;
pinfo->gso_size = 0;
skb_header_release(p);
nskb->prev = p;
NAPI_GRO_CB(nskb)->last = p;

nskb->data_len += p->len;
nskb->truesize += p->truesize;
Expand All @@ -3030,8 +3030,8 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)

__skb_pull(skb, offset);

p->prev->next = skb;
p->prev = skb;
NAPI_GRO_CB(p)->last->next = skb;
NAPI_GRO_CB(p)->last = skb;
skb_header_release(skb);

done:
Expand Down
6 changes: 5 additions & 1 deletion net/ipv4/tcp_input.c
Original file line number Diff line number Diff line change
Expand Up @@ -5645,7 +5645,11 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack,
tcp_fastopen_cache_set(sk, mss, cookie, syn_drop);

if (data) { /* Retransmit unacked data in SYN */
tcp_retransmit_skb(sk, data);
tcp_for_write_queue_from(data, sk) {
if (data == tcp_send_head(sk) ||
__tcp_retransmit_skb(sk, data))
break;
}
tcp_rearm_rto(sk);
return true;
}
Expand Down
15 changes: 10 additions & 5 deletions net/ipv4/tcp_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -2309,12 +2309,11 @@ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *to,
* state updates are done by the caller. Returns non-zero if an
* error occurred which prevented the send.
*/
int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
{
struct tcp_sock *tp = tcp_sk(sk);
struct inet_connection_sock *icsk = inet_csk(sk);
unsigned int cur_mss;
int err;

/* Inconslusive MTU probe */
if (icsk->icsk_mtup.probe_size) {
Expand Down Expand Up @@ -2387,11 +2386,17 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
if (unlikely(NET_IP_ALIGN && ((unsigned long)skb->data & 3))) {
struct sk_buff *nskb = __pskb_copy(skb, MAX_TCP_HEADER,
GFP_ATOMIC);
err = nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) :
-ENOBUFS;
return nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) :
-ENOBUFS;
} else {
err = tcp_transmit_skb(sk, skb, 1, GFP_ATOMIC);
return tcp_transmit_skb(sk, skb, 1, GFP_ATOMIC);
}
}

int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
{
struct tcp_sock *tp = tcp_sk(sk);
int err = __tcp_retransmit_skb(sk, skb);

if (err == 0) {
/* Update global TCP statistics. */
Expand Down

0 comments on commit 1b3c393

Please sign in to comment.