diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2016-01-12 05:01:12 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2016-01-12 05:01:12 -0500 |
commit | 1f16f116b01c110db20ab808562c8b8bc3ee3d6e (patch) | |
tree | 44db563f64cf5f8d62af8f99a61e2b248c44ea3a /net/ipv6/tcp_ipv6.c | |
parent | 03724ac3d48f8f0e3caf1d30fa134f8fd96c94e2 (diff) | |
parent | f9eccf24615672896dc13251410c3f2f33a14f95 (diff) |
Merge branches 'clockevents/4.4-fixes' and 'clockevents/4.5-fixes' of http://git.linaro.org/people/daniel.lezcano/linux into timers/urgent
Pull in fixes from Daniel Lezcano:
- Fix the vt8500 timer leading to a system lock up when dealing with too
small delta (Roman Volkov)
- Select the CLKSRC_MMIO when the fsl_ftm_timer is enabled with COMPILE_TEST
(Daniel Lezcano)
- Prevent to compile timers using the 'iomem' API when the architecture has
not HAS_IOMEM set (Richard Weinberger)
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 35 |
1 files changed, 20 insertions, 15 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index c5429a636f1a..6b8a8a9091fa 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -93,10 +93,9 @@ static void inet6_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) | |||
93 | { | 93 | { |
94 | struct dst_entry *dst = skb_dst(skb); | 94 | struct dst_entry *dst = skb_dst(skb); |
95 | 95 | ||
96 | if (dst) { | 96 | if (dst && dst_hold_safe(dst)) { |
97 | const struct rt6_info *rt = (const struct rt6_info *)dst; | 97 | const struct rt6_info *rt = (const struct rt6_info *)dst; |
98 | 98 | ||
99 | dst_hold(dst); | ||
100 | sk->sk_rx_dst = dst; | 99 | sk->sk_rx_dst = dst; |
101 | inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; | 100 | inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; |
102 | inet6_sk(sk)->rx_dst_cookie = rt6_get_cookie(rt); | 101 | inet6_sk(sk)->rx_dst_cookie = rt6_get_cookie(rt); |
@@ -120,6 +119,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
120 | struct ipv6_pinfo *np = inet6_sk(sk); | 119 | struct ipv6_pinfo *np = inet6_sk(sk); |
121 | struct tcp_sock *tp = tcp_sk(sk); | 120 | struct tcp_sock *tp = tcp_sk(sk); |
122 | struct in6_addr *saddr = NULL, *final_p, final; | 121 | struct in6_addr *saddr = NULL, *final_p, final; |
122 | struct ipv6_txoptions *opt; | ||
123 | struct flowi6 fl6; | 123 | struct flowi6 fl6; |
124 | struct dst_entry *dst; | 124 | struct dst_entry *dst; |
125 | int addr_type; | 125 | int addr_type; |
@@ -235,7 +235,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
235 | fl6.fl6_dport = usin->sin6_port; | 235 | fl6.fl6_dport = usin->sin6_port; |
236 | fl6.fl6_sport = inet->inet_sport; | 236 | fl6.fl6_sport = inet->inet_sport; |
237 | 237 | ||
238 | final_p = fl6_update_dst(&fl6, np->opt, &final); | 238 | opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk)); |
239 | final_p = fl6_update_dst(&fl6, opt, &final); | ||
239 | 240 | ||
240 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); | 241 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); |
241 | 242 | ||
@@ -255,7 +256,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
255 | inet->inet_rcv_saddr = LOOPBACK4_IPV6; | 256 | inet->inet_rcv_saddr = LOOPBACK4_IPV6; |
256 | 257 | ||
257 | sk->sk_gso_type = SKB_GSO_TCPV6; | 258 | sk->sk_gso_type = SKB_GSO_TCPV6; |
258 | __ip6_dst_store(sk, dst, NULL, NULL); | 259 | ip6_dst_store(sk, dst, NULL, NULL); |
259 | 260 | ||
260 | if (tcp_death_row.sysctl_tw_recycle && | 261 | if (tcp_death_row.sysctl_tw_recycle && |
261 | !tp->rx_opt.ts_recent_stamp && | 262 | !tp->rx_opt.ts_recent_stamp && |
@@ -263,9 +264,9 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
263 | tcp_fetch_timewait_stamp(sk, dst); | 264 | tcp_fetch_timewait_stamp(sk, dst); |
264 | 265 | ||
265 | icsk->icsk_ext_hdr_len = 0; | 266 | icsk->icsk_ext_hdr_len = 0; |
266 | if (np->opt) | 267 | if (opt) |
267 | icsk->icsk_ext_hdr_len = (np->opt->opt_flen + | 268 | icsk->icsk_ext_hdr_len = opt->opt_flen + |
268 | np->opt->opt_nflen); | 269 | opt->opt_nflen; |
269 | 270 | ||
270 | tp->rx_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr); | 271 | tp->rx_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr); |
271 | 272 | ||
@@ -461,7 +462,8 @@ static int tcp_v6_send_synack(const struct sock *sk, struct dst_entry *dst, | |||
461 | if (np->repflow && ireq->pktopts) | 462 | if (np->repflow && ireq->pktopts) |
462 | fl6->flowlabel = ip6_flowlabel(ipv6_hdr(ireq->pktopts)); | 463 | fl6->flowlabel = ip6_flowlabel(ipv6_hdr(ireq->pktopts)); |
463 | 464 | ||
464 | err = ip6_xmit(sk, skb, fl6, np->opt, np->tclass); | 465 | err = ip6_xmit(sk, skb, fl6, rcu_dereference(np->opt), |
466 | np->tclass); | ||
465 | err = net_xmit_eval(err); | 467 | err = net_xmit_eval(err); |
466 | } | 468 | } |
467 | 469 | ||
@@ -972,6 +974,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff * | |||
972 | struct inet_request_sock *ireq; | 974 | struct inet_request_sock *ireq; |
973 | struct ipv6_pinfo *newnp; | 975 | struct ipv6_pinfo *newnp; |
974 | const struct ipv6_pinfo *np = inet6_sk(sk); | 976 | const struct ipv6_pinfo *np = inet6_sk(sk); |
977 | struct ipv6_txoptions *opt; | ||
975 | struct tcp6_sock *newtcp6sk; | 978 | struct tcp6_sock *newtcp6sk; |
976 | struct inet_sock *newinet; | 979 | struct inet_sock *newinet; |
977 | struct tcp_sock *newtp; | 980 | struct tcp_sock *newtp; |
@@ -1056,7 +1059,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff * | |||
1056 | */ | 1059 | */ |
1057 | 1060 | ||
1058 | newsk->sk_gso_type = SKB_GSO_TCPV6; | 1061 | newsk->sk_gso_type = SKB_GSO_TCPV6; |
1059 | __ip6_dst_store(newsk, dst, NULL, NULL); | 1062 | ip6_dst_store(newsk, dst, NULL, NULL); |
1060 | inet6_sk_rx_dst_set(newsk, skb); | 1063 | inet6_sk_rx_dst_set(newsk, skb); |
1061 | 1064 | ||
1062 | newtcp6sk = (struct tcp6_sock *)newsk; | 1065 | newtcp6sk = (struct tcp6_sock *)newsk; |
@@ -1098,13 +1101,15 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff * | |||
1098 | but we make one more one thing there: reattach optmem | 1101 | but we make one more one thing there: reattach optmem |
1099 | to newsk. | 1102 | to newsk. |
1100 | */ | 1103 | */ |
1101 | if (np->opt) | 1104 | opt = rcu_dereference(np->opt); |
1102 | newnp->opt = ipv6_dup_options(newsk, np->opt); | 1105 | if (opt) { |
1103 | 1106 | opt = ipv6_dup_options(newsk, opt); | |
1107 | RCU_INIT_POINTER(newnp->opt, opt); | ||
1108 | } | ||
1104 | inet_csk(newsk)->icsk_ext_hdr_len = 0; | 1109 | inet_csk(newsk)->icsk_ext_hdr_len = 0; |
1105 | if (newnp->opt) | 1110 | if (opt) |
1106 | inet_csk(newsk)->icsk_ext_hdr_len = (newnp->opt->opt_nflen + | 1111 | inet_csk(newsk)->icsk_ext_hdr_len = opt->opt_nflen + |
1107 | newnp->opt->opt_flen); | 1112 | opt->opt_flen; |
1108 | 1113 | ||
1109 | tcp_ca_openreq_child(newsk, dst); | 1114 | tcp_ca_openreq_child(newsk, dst); |
1110 | 1115 | ||