diff options
Diffstat (limited to 'net/ipv4')
| -rw-r--r-- | net/ipv4/devinet.c | 60 | ||||
| -rw-r--r-- | net/ipv4/esp4.c | 6 | ||||
| -rw-r--r-- | net/ipv4/ip_fragment.c | 14 | ||||
| -rw-r--r-- | net/ipv4/netfilter/ipt_rpfilter.c | 8 | ||||
| -rw-r--r-- | net/ipv4/syncookies.c | 4 | ||||
| -rw-r--r-- | net/ipv4/tcp_input.c | 64 | ||||
| -rw-r--r-- | net/ipv4/tcp_output.c | 9 |
7 files changed, 104 insertions, 61 deletions
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 96083b7a436b..c6287cd978c2 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c | |||
| @@ -587,13 +587,16 @@ static void check_lifetime(struct work_struct *work) | |||
| 587 | { | 587 | { |
| 588 | unsigned long now, next, next_sec, next_sched; | 588 | unsigned long now, next, next_sec, next_sched; |
| 589 | struct in_ifaddr *ifa; | 589 | struct in_ifaddr *ifa; |
| 590 | struct hlist_node *n; | ||
| 590 | int i; | 591 | int i; |
| 591 | 592 | ||
| 592 | now = jiffies; | 593 | now = jiffies; |
| 593 | next = round_jiffies_up(now + ADDR_CHECK_FREQUENCY); | 594 | next = round_jiffies_up(now + ADDR_CHECK_FREQUENCY); |
| 594 | 595 | ||
| 595 | rcu_read_lock(); | ||
| 596 | for (i = 0; i < IN4_ADDR_HSIZE; i++) { | 596 | for (i = 0; i < IN4_ADDR_HSIZE; i++) { |
| 597 | bool change_needed = false; | ||
| 598 | |||
| 599 | rcu_read_lock(); | ||
| 597 | hlist_for_each_entry_rcu(ifa, &inet_addr_lst[i], hash) { | 600 | hlist_for_each_entry_rcu(ifa, &inet_addr_lst[i], hash) { |
| 598 | unsigned long age; | 601 | unsigned long age; |
| 599 | 602 | ||
| @@ -606,16 +609,7 @@ static void check_lifetime(struct work_struct *work) | |||
| 606 | 609 | ||
| 607 | if (ifa->ifa_valid_lft != INFINITY_LIFE_TIME && | 610 | if (ifa->ifa_valid_lft != INFINITY_LIFE_TIME && |
| 608 | age >= ifa->ifa_valid_lft) { | 611 | age >= ifa->ifa_valid_lft) { |
| 609 | struct in_ifaddr **ifap ; | 612 | change_needed = true; |
| 610 | |||
| 611 | rtnl_lock(); | ||
| 612 | for (ifap = &ifa->ifa_dev->ifa_list; | ||
| 613 | *ifap != NULL; ifap = &ifa->ifa_next) { | ||
| 614 | if (*ifap == ifa) | ||
| 615 | inet_del_ifa(ifa->ifa_dev, | ||
| 616 | ifap, 1); | ||
| 617 | } | ||
| 618 | rtnl_unlock(); | ||
| 619 | } else if (ifa->ifa_preferred_lft == | 613 | } else if (ifa->ifa_preferred_lft == |
| 620 | INFINITY_LIFE_TIME) { | 614 | INFINITY_LIFE_TIME) { |
| 621 | continue; | 615 | continue; |
| @@ -625,10 +619,8 @@ static void check_lifetime(struct work_struct *work) | |||
| 625 | next = ifa->ifa_tstamp + | 619 | next = ifa->ifa_tstamp + |
| 626 | ifa->ifa_valid_lft * HZ; | 620 | ifa->ifa_valid_lft * HZ; |
| 627 | 621 | ||
| 628 | if (!(ifa->ifa_flags & IFA_F_DEPRECATED)) { | 622 | if (!(ifa->ifa_flags & IFA_F_DEPRECATED)) |
| 629 | ifa->ifa_flags |= IFA_F_DEPRECATED; | 623 | change_needed = true; |
| 630 | rtmsg_ifa(RTM_NEWADDR, ifa, NULL, 0); | ||
| 631 | } | ||
| 632 | } else if (time_before(ifa->ifa_tstamp + | 624 | } else if (time_before(ifa->ifa_tstamp + |
| 633 | ifa->ifa_preferred_lft * HZ, | 625 | ifa->ifa_preferred_lft * HZ, |
| 634 | next)) { | 626 | next)) { |
| @@ -636,8 +628,42 @@ static void check_lifetime(struct work_struct *work) | |||
| 636 | ifa->ifa_preferred_lft * HZ; | 628 | ifa->ifa_preferred_lft * HZ; |
| 637 | } | 629 | } |
| 638 | } | 630 | } |
| 631 | rcu_read_unlock(); | ||
| 632 | if (!change_needed) | ||
| 633 | continue; | ||
| 634 | rtnl_lock(); | ||
| 635 | hlist_for_each_entry_safe(ifa, n, &inet_addr_lst[i], hash) { | ||
| 636 | unsigned long age; | ||
| 637 | |||
| 638 | if (ifa->ifa_flags & IFA_F_PERMANENT) | ||
| 639 | continue; | ||
| 640 | |||
| 641 | /* We try to batch several events at once. */ | ||
| 642 | age = (now - ifa->ifa_tstamp + | ||
| 643 | ADDRCONF_TIMER_FUZZ_MINUS) / HZ; | ||
| 644 | |||
| 645 | if (ifa->ifa_valid_lft != INFINITY_LIFE_TIME && | ||
| 646 | age >= ifa->ifa_valid_lft) { | ||
| 647 | struct in_ifaddr **ifap; | ||
| 648 | |||
| 649 | for (ifap = &ifa->ifa_dev->ifa_list; | ||
| 650 | *ifap != NULL; ifap = &(*ifap)->ifa_next) { | ||
| 651 | if (*ifap == ifa) { | ||
| 652 | inet_del_ifa(ifa->ifa_dev, | ||
| 653 | ifap, 1); | ||
| 654 | break; | ||
| 655 | } | ||
| 656 | } | ||
| 657 | } else if (ifa->ifa_preferred_lft != | ||
| 658 | INFINITY_LIFE_TIME && | ||
| 659 | age >= ifa->ifa_preferred_lft && | ||
| 660 | !(ifa->ifa_flags & IFA_F_DEPRECATED)) { | ||
| 661 | ifa->ifa_flags |= IFA_F_DEPRECATED; | ||
| 662 | rtmsg_ifa(RTM_NEWADDR, ifa, NULL, 0); | ||
| 663 | } | ||
| 664 | } | ||
| 665 | rtnl_unlock(); | ||
| 639 | } | 666 | } |
| 640 | rcu_read_unlock(); | ||
| 641 | 667 | ||
| 642 | next_sec = round_jiffies_up(next); | 668 | next_sec = round_jiffies_up(next); |
| 643 | next_sched = next; | 669 | next_sched = next; |
| @@ -804,6 +830,8 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg | |||
| 804 | return -EEXIST; | 830 | return -EEXIST; |
| 805 | ifa = ifa_existing; | 831 | ifa = ifa_existing; |
| 806 | set_ifa_lifetime(ifa, valid_lft, prefered_lft); | 832 | set_ifa_lifetime(ifa, valid_lft, prefered_lft); |
| 833 | cancel_delayed_work(&check_lifetime_work); | ||
| 834 | schedule_delayed_work(&check_lifetime_work, 0); | ||
| 807 | rtmsg_ifa(RTM_NEWADDR, ifa, nlh, NETLINK_CB(skb).portid); | 835 | rtmsg_ifa(RTM_NEWADDR, ifa, nlh, NETLINK_CB(skb).portid); |
| 808 | blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa); | 836 | blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa); |
| 809 | } | 837 | } |
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 3b4f0cd2e63e..4cfe34d4cc96 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c | |||
| @@ -139,8 +139,6 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) | |||
| 139 | 139 | ||
| 140 | /* skb is pure payload to encrypt */ | 140 | /* skb is pure payload to encrypt */ |
| 141 | 141 | ||
| 142 | err = -ENOMEM; | ||
| 143 | |||
| 144 | esp = x->data; | 142 | esp = x->data; |
| 145 | aead = esp->aead; | 143 | aead = esp->aead; |
| 146 | alen = crypto_aead_authsize(aead); | 144 | alen = crypto_aead_authsize(aead); |
| @@ -176,8 +174,10 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) | |||
| 176 | } | 174 | } |
| 177 | 175 | ||
| 178 | tmp = esp_alloc_tmp(aead, nfrags + sglists, seqhilen); | 176 | tmp = esp_alloc_tmp(aead, nfrags + sglists, seqhilen); |
| 179 | if (!tmp) | 177 | if (!tmp) { |
| 178 | err = -ENOMEM; | ||
| 180 | goto error; | 179 | goto error; |
| 180 | } | ||
| 181 | 181 | ||
| 182 | seqhi = esp_tmp_seqhi(tmp); | 182 | seqhi = esp_tmp_seqhi(tmp); |
| 183 | iv = esp_tmp_iv(aead, tmp, seqhilen); | 183 | iv = esp_tmp_iv(aead, tmp, seqhilen); |
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index a6445b843ef4..52c273ea05c3 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
| @@ -248,8 +248,7 @@ static void ip_expire(unsigned long arg) | |||
| 248 | if (!head->dev) | 248 | if (!head->dev) |
| 249 | goto out_rcu_unlock; | 249 | goto out_rcu_unlock; |
| 250 | 250 | ||
| 251 | /* skb dst is stale, drop it, and perform route lookup again */ | 251 | /* skb has no dst, perform route lookup again */ |
| 252 | skb_dst_drop(head); | ||
| 253 | iph = ip_hdr(head); | 252 | iph = ip_hdr(head); |
| 254 | err = ip_route_input_noref(head, iph->daddr, iph->saddr, | 253 | err = ip_route_input_noref(head, iph->daddr, iph->saddr, |
| 255 | iph->tos, head->dev); | 254 | iph->tos, head->dev); |
| @@ -523,9 +522,16 @@ found: | |||
| 523 | qp->q.max_size = skb->len + ihl; | 522 | qp->q.max_size = skb->len + ihl; |
| 524 | 523 | ||
| 525 | if (qp->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && | 524 | if (qp->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && |
| 526 | qp->q.meat == qp->q.len) | 525 | qp->q.meat == qp->q.len) { |
| 527 | return ip_frag_reasm(qp, prev, dev); | 526 | unsigned long orefdst = skb->_skb_refdst; |
| 528 | 527 | ||
| 528 | skb->_skb_refdst = 0UL; | ||
| 529 | err = ip_frag_reasm(qp, prev, dev); | ||
| 530 | skb->_skb_refdst = orefdst; | ||
| 531 | return err; | ||
| 532 | } | ||
| 533 | |||
| 534 | skb_dst_drop(skb); | ||
| 529 | inet_frag_lru_move(&qp->q); | 535 | inet_frag_lru_move(&qp->q); |
| 530 | return -EINPROGRESS; | 536 | return -EINPROGRESS; |
| 531 | 537 | ||
diff --git a/net/ipv4/netfilter/ipt_rpfilter.c b/net/ipv4/netfilter/ipt_rpfilter.c index c30130062cd6..c49dcd0284a0 100644 --- a/net/ipv4/netfilter/ipt_rpfilter.c +++ b/net/ipv4/netfilter/ipt_rpfilter.c | |||
| @@ -66,6 +66,12 @@ static bool rpfilter_lookup_reverse(struct flowi4 *fl4, | |||
| 66 | return dev_match; | 66 | return dev_match; |
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | static bool rpfilter_is_local(const struct sk_buff *skb) | ||
| 70 | { | ||
| 71 | const struct rtable *rt = skb_rtable(skb); | ||
| 72 | return rt && (rt->rt_flags & RTCF_LOCAL); | ||
| 73 | } | ||
| 74 | |||
| 69 | static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par) | 75 | static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par) |
| 70 | { | 76 | { |
| 71 | const struct xt_rpfilter_info *info; | 77 | const struct xt_rpfilter_info *info; |
| @@ -76,7 +82,7 @@ static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
| 76 | info = par->matchinfo; | 82 | info = par->matchinfo; |
| 77 | invert = info->flags & XT_RPFILTER_INVERT; | 83 | invert = info->flags & XT_RPFILTER_INVERT; |
| 78 | 84 | ||
| 79 | if (par->in->flags & IFF_LOOPBACK) | 85 | if (rpfilter_is_local(skb)) |
| 80 | return true ^ invert; | 86 | return true ^ invert; |
| 81 | 87 | ||
| 82 | iph = ip_hdr(skb); | 88 | iph = ip_hdr(skb); |
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index ef54377fb11c..397e0f69435f 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c | |||
| @@ -349,8 +349,8 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, | |||
| 349 | * hasn't changed since we received the original syn, but I see | 349 | * hasn't changed since we received the original syn, but I see |
| 350 | * no easy way to do this. | 350 | * no easy way to do this. |
| 351 | */ | 351 | */ |
| 352 | flowi4_init_output(&fl4, 0, sk->sk_mark, RT_CONN_FLAGS(sk), | 352 | flowi4_init_output(&fl4, sk->sk_bound_dev_if, sk->sk_mark, |
| 353 | RT_SCOPE_UNIVERSE, IPPROTO_TCP, | 353 | RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, IPPROTO_TCP, |
| 354 | inet_sk_flowi_flags(sk), | 354 | inet_sk_flowi_flags(sk), |
| 355 | (opt && opt->srr) ? opt->faddr : ireq->rmt_addr, | 355 | (opt && opt->srr) ? opt->faddr : ireq->rmt_addr, |
| 356 | ireq->loc_addr, th->source, th->dest); | 356 | ireq->loc_addr, th->source, th->dest); |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 3bd55bad230a..13b9c08fc158 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
| @@ -113,6 +113,7 @@ int sysctl_tcp_early_retrans __read_mostly = 2; | |||
| 113 | #define FLAG_DSACKING_ACK 0x800 /* SACK blocks contained D-SACK info */ | 113 | #define FLAG_DSACKING_ACK 0x800 /* SACK blocks contained D-SACK info */ |
| 114 | #define FLAG_NONHEAD_RETRANS_ACKED 0x1000 /* Non-head rexmitted data was ACKed */ | 114 | #define FLAG_NONHEAD_RETRANS_ACKED 0x1000 /* Non-head rexmitted data was ACKed */ |
| 115 | #define FLAG_SACK_RENEGING 0x2000 /* snd_una advanced to a sacked seq */ | 115 | #define FLAG_SACK_RENEGING 0x2000 /* snd_una advanced to a sacked seq */ |
| 116 | #define FLAG_UPDATE_TS_RECENT 0x4000 /* tcp_replace_ts_recent() */ | ||
| 116 | 117 | ||
| 117 | #define FLAG_ACKED (FLAG_DATA_ACKED|FLAG_SYN_ACKED) | 118 | #define FLAG_ACKED (FLAG_DATA_ACKED|FLAG_SYN_ACKED) |
| 118 | #define FLAG_NOT_DUP (FLAG_DATA|FLAG_WIN_UPDATE|FLAG_ACKED) | 119 | #define FLAG_NOT_DUP (FLAG_DATA|FLAG_WIN_UPDATE|FLAG_ACKED) |
| @@ -3564,6 +3565,27 @@ static void tcp_send_challenge_ack(struct sock *sk) | |||
| 3564 | } | 3565 | } |
| 3565 | } | 3566 | } |
| 3566 | 3567 | ||
| 3568 | static void tcp_store_ts_recent(struct tcp_sock *tp) | ||
| 3569 | { | ||
| 3570 | tp->rx_opt.ts_recent = tp->rx_opt.rcv_tsval; | ||
| 3571 | tp->rx_opt.ts_recent_stamp = get_seconds(); | ||
| 3572 | } | ||
| 3573 | |||
| 3574 | static void tcp_replace_ts_recent(struct tcp_sock *tp, u32 seq) | ||
| 3575 | { | ||
| 3576 | if (tp->rx_opt.saw_tstamp && !after(seq, tp->rcv_wup)) { | ||
| 3577 | /* PAWS bug workaround wrt. ACK frames, the PAWS discard | ||
| 3578 | * extra check below makes sure this can only happen | ||
| 3579 | * for pure ACK frames. -DaveM | ||
| 3580 | * | ||
| 3581 | * Not only, also it occurs for expired timestamps. | ||
| 3582 | */ | ||
| 3583 | |||
| 3584 | if (tcp_paws_check(&tp->rx_opt, 0)) | ||
| 3585 | tcp_store_ts_recent(tp); | ||
| 3586 | } | ||
| 3587 | } | ||
| 3588 | |||
| 3567 | /* This routine deals with incoming acks, but not outgoing ones. */ | 3589 | /* This routine deals with incoming acks, but not outgoing ones. */ |
| 3568 | static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) | 3590 | static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) |
| 3569 | { | 3591 | { |
| @@ -3607,6 +3629,12 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) | |||
| 3607 | prior_fackets = tp->fackets_out; | 3629 | prior_fackets = tp->fackets_out; |
| 3608 | prior_in_flight = tcp_packets_in_flight(tp); | 3630 | prior_in_flight = tcp_packets_in_flight(tp); |
| 3609 | 3631 | ||
| 3632 | /* ts_recent update must be made after we are sure that the packet | ||
| 3633 | * is in window. | ||
| 3634 | */ | ||
| 3635 | if (flag & FLAG_UPDATE_TS_RECENT) | ||
| 3636 | tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq); | ||
| 3637 | |||
| 3610 | if (!(flag & FLAG_SLOWPATH) && after(ack, prior_snd_una)) { | 3638 | if (!(flag & FLAG_SLOWPATH) && after(ack, prior_snd_una)) { |
| 3611 | /* Window is constant, pure forward advance. | 3639 | /* Window is constant, pure forward advance. |
| 3612 | * No more checks are required. | 3640 | * No more checks are required. |
| @@ -3927,27 +3955,6 @@ const u8 *tcp_parse_md5sig_option(const struct tcphdr *th) | |||
| 3927 | EXPORT_SYMBOL(tcp_parse_md5sig_option); | 3955 | EXPORT_SYMBOL(tcp_parse_md5sig_option); |
| 3928 | #endif | 3956 | #endif |
| 3929 | 3957 | ||
| 3930 | static inline void tcp_store_ts_recent(struct tcp_sock *tp) | ||
| 3931 | { | ||
| 3932 | tp->rx_opt.ts_recent = tp->rx_opt.rcv_tsval; | ||
| 3933 | tp->rx_opt.ts_recent_stamp = get_seconds(); | ||
| 3934 | } | ||
| 3935 | |||
| 3936 | static inline void tcp_replace_ts_recent(struct tcp_sock *tp, u32 seq) | ||
| 3937 | { | ||
| 3938 | if (tp->rx_opt.saw_tstamp && !after(seq, tp->rcv_wup)) { | ||
| 3939 | /* PAWS bug workaround wrt. ACK frames, the PAWS discard | ||
| 3940 | * extra check below makes sure this can only happen | ||
| 3941 | * for pure ACK frames. -DaveM | ||
| 3942 | * | ||
| 3943 | * Not only, also it occurs for expired timestamps. | ||
| 3944 | */ | ||
| 3945 | |||
| 3946 | if (tcp_paws_check(&tp->rx_opt, 0)) | ||
| 3947 | tcp_store_ts_recent(tp); | ||
| 3948 | } | ||
| 3949 | } | ||
| 3950 | |||
| 3951 | /* Sorry, PAWS as specified is broken wrt. pure-ACKs -DaveM | 3958 | /* Sorry, PAWS as specified is broken wrt. pure-ACKs -DaveM |
| 3952 | * | 3959 | * |
| 3953 | * It is not fatal. If this ACK does _not_ change critical state (seqs, window) | 3960 | * It is not fatal. If this ACK does _not_ change critical state (seqs, window) |
| @@ -5543,14 +5550,9 @@ slow_path: | |||
| 5543 | return 0; | 5550 | return 0; |
| 5544 | 5551 | ||
| 5545 | step5: | 5552 | step5: |
| 5546 | if (tcp_ack(sk, skb, FLAG_SLOWPATH) < 0) | 5553 | if (tcp_ack(sk, skb, FLAG_SLOWPATH | FLAG_UPDATE_TS_RECENT) < 0) |
| 5547 | goto discard; | 5554 | goto discard; |
| 5548 | 5555 | ||
| 5549 | /* ts_recent update must be made after we are sure that the packet | ||
| 5550 | * is in window. | ||
| 5551 | */ | ||
| 5552 | tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq); | ||
| 5553 | |||
| 5554 | tcp_rcv_rtt_measure_ts(sk, skb); | 5556 | tcp_rcv_rtt_measure_ts(sk, skb); |
| 5555 | 5557 | ||
| 5556 | /* Process urgent data. */ | 5558 | /* Process urgent data. */ |
| @@ -5986,7 +5988,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
| 5986 | 5988 | ||
| 5987 | /* step 5: check the ACK field */ | 5989 | /* step 5: check the ACK field */ |
| 5988 | if (true) { | 5990 | if (true) { |
| 5989 | int acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH) > 0; | 5991 | int acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH | |
| 5992 | FLAG_UPDATE_TS_RECENT) > 0; | ||
| 5990 | 5993 | ||
| 5991 | switch (sk->sk_state) { | 5994 | switch (sk->sk_state) { |
| 5992 | case TCP_SYN_RECV: | 5995 | case TCP_SYN_RECV: |
| @@ -6137,11 +6140,6 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
| 6137 | } | 6140 | } |
| 6138 | } | 6141 | } |
| 6139 | 6142 | ||
| 6140 | /* ts_recent update must be made after we are sure that the packet | ||
| 6141 | * is in window. | ||
| 6142 | */ | ||
| 6143 | tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq); | ||
| 6144 | |||
| 6145 | /* step 6: check the URG bit */ | 6143 | /* step 6: check the URG bit */ |
| 6146 | tcp_urg(sk, skb, th); | 6144 | tcp_urg(sk, skb, th); |
| 6147 | 6145 | ||
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 5d0b4387cba6..509912a5ff98 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
| @@ -2388,8 +2388,12 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) | |||
| 2388 | */ | 2388 | */ |
| 2389 | TCP_SKB_CB(skb)->when = tcp_time_stamp; | 2389 | TCP_SKB_CB(skb)->when = tcp_time_stamp; |
| 2390 | 2390 | ||
| 2391 | /* make sure skb->data is aligned on arches that require it */ | 2391 | /* make sure skb->data is aligned on arches that require it |
| 2392 | if (unlikely(NET_IP_ALIGN && ((unsigned long)skb->data & 3))) { | 2392 | * and check if ack-trimming & collapsing extended the headroom |
| 2393 | * beyond what csum_start can cover. | ||
| 2394 | */ | ||
| 2395 | if (unlikely((NET_IP_ALIGN && ((unsigned long)skb->data & 3)) || | ||
| 2396 | skb_headroom(skb) >= 0xFFFF)) { | ||
| 2393 | struct sk_buff *nskb = __pskb_copy(skb, MAX_TCP_HEADER, | 2397 | struct sk_buff *nskb = __pskb_copy(skb, MAX_TCP_HEADER, |
| 2394 | GFP_ATOMIC); | 2398 | GFP_ATOMIC); |
| 2395 | return nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) : | 2399 | return nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) : |
| @@ -2709,6 +2713,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, | |||
| 2709 | skb_reserve(skb, MAX_TCP_HEADER); | 2713 | skb_reserve(skb, MAX_TCP_HEADER); |
| 2710 | 2714 | ||
| 2711 | skb_dst_set(skb, dst); | 2715 | skb_dst_set(skb, dst); |
| 2716 | security_skb_owned_by(skb, sk); | ||
| 2712 | 2717 | ||
| 2713 | mss = dst_metric_advmss(dst); | 2718 | mss = dst_metric_advmss(dst); |
| 2714 | if (tp->rx_opt.user_mss && tp->rx_opt.user_mss < mss) | 2719 | if (tp->rx_opt.user_mss && tp->rx_opt.user_mss < mss) |
