aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/tcp_ipv6.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2016-01-12 05:01:12 -0500
committerThomas Gleixner <tglx@linutronix.de>2016-01-12 05:01:12 -0500
commit1f16f116b01c110db20ab808562c8b8bc3ee3d6e (patch)
tree44db563f64cf5f8d62af8f99a61e2b248c44ea3a /net/ipv6/tcp_ipv6.c
parent03724ac3d48f8f0e3caf1d30fa134f8fd96c94e2 (diff)
parentf9eccf24615672896dc13251410c3f2f33a14f95 (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.c35
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