aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/tcp_ipv6.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
-rw-r--r--net/ipv6/tcp_ipv6.c54
1 files changed, 32 insertions, 22 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index c5429a636f1a..db9f1c318afc 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,10 @@ 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 rcu_read_lock();
466 err = ip6_xmit(sk, skb, fl6, rcu_dereference(np->opt),
467 np->tclass);
468 rcu_read_unlock();
465 err = net_xmit_eval(err); 469 err = net_xmit_eval(err);
466 } 470 }
467 471
@@ -852,7 +856,9 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb)
852 856
853#ifdef CONFIG_TCP_MD5SIG 857#ifdef CONFIG_TCP_MD5SIG
854 hash_location = tcp_parse_md5sig_option(th); 858 hash_location = tcp_parse_md5sig_option(th);
855 if (!sk && hash_location) { 859 if (sk && sk_fullsock(sk)) {
860 key = tcp_v6_md5_do_lookup(sk, &ipv6h->saddr);
861 } else if (hash_location) {
856 /* 862 /*
857 * active side is lost. Try to find listening socket through 863 * active side is lost. Try to find listening socket through
858 * source port, and then find md5 key through listening socket. 864 * source port, and then find md5 key through listening socket.
@@ -875,8 +881,6 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb)
875 genhash = tcp_v6_md5_hash_skb(newhash, key, NULL, skb); 881 genhash = tcp_v6_md5_hash_skb(newhash, key, NULL, skb);
876 if (genhash || memcmp(hash_location, newhash, 16) != 0) 882 if (genhash || memcmp(hash_location, newhash, 16) != 0)
877 goto release_sk1; 883 goto release_sk1;
878 } else {
879 key = sk ? tcp_v6_md5_do_lookup(sk, &ipv6h->saddr) : NULL;
880 } 884 }
881#endif 885#endif
882 886
@@ -972,6 +976,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
972 struct inet_request_sock *ireq; 976 struct inet_request_sock *ireq;
973 struct ipv6_pinfo *newnp; 977 struct ipv6_pinfo *newnp;
974 const struct ipv6_pinfo *np = inet6_sk(sk); 978 const struct ipv6_pinfo *np = inet6_sk(sk);
979 struct ipv6_txoptions *opt;
975 struct tcp6_sock *newtcp6sk; 980 struct tcp6_sock *newtcp6sk;
976 struct inet_sock *newinet; 981 struct inet_sock *newinet;
977 struct tcp_sock *newtp; 982 struct tcp_sock *newtp;
@@ -1056,7 +1061,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
1056 */ 1061 */
1057 1062
1058 newsk->sk_gso_type = SKB_GSO_TCPV6; 1063 newsk->sk_gso_type = SKB_GSO_TCPV6;
1059 __ip6_dst_store(newsk, dst, NULL, NULL); 1064 ip6_dst_store(newsk, dst, NULL, NULL);
1060 inet6_sk_rx_dst_set(newsk, skb); 1065 inet6_sk_rx_dst_set(newsk, skb);
1061 1066
1062 newtcp6sk = (struct tcp6_sock *)newsk; 1067 newtcp6sk = (struct tcp6_sock *)newsk;
@@ -1098,13 +1103,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 1103 but we make one more one thing there: reattach optmem
1099 to newsk. 1104 to newsk.
1100 */ 1105 */
1101 if (np->opt) 1106 opt = rcu_dereference(np->opt);
1102 newnp->opt = ipv6_dup_options(newsk, np->opt); 1107 if (opt) {
1103 1108 opt = ipv6_dup_options(newsk, opt);
1109 RCU_INIT_POINTER(newnp->opt, opt);
1110 }
1104 inet_csk(newsk)->icsk_ext_hdr_len = 0; 1111 inet_csk(newsk)->icsk_ext_hdr_len = 0;
1105 if (newnp->opt) 1112 if (opt)
1106 inet_csk(newsk)->icsk_ext_hdr_len = (newnp->opt->opt_nflen + 1113 inet_csk(newsk)->icsk_ext_hdr_len = opt->opt_nflen +
1107 newnp->opt->opt_flen); 1114 opt->opt_flen;
1108 1115
1109 tcp_ca_openreq_child(newsk, dst); 1116 tcp_ca_openreq_child(newsk, dst);
1110 1117
@@ -1130,7 +1137,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
1130 */ 1137 */
1131 tcp_md5_do_add(newsk, (union tcp_md5_addr *)&newsk->sk_v6_daddr, 1138 tcp_md5_do_add(newsk, (union tcp_md5_addr *)&newsk->sk_v6_daddr,
1132 AF_INET6, key->key, key->keylen, 1139 AF_INET6, key->key, key->keylen,
1133 sk_gfp_atomic(sk, GFP_ATOMIC)); 1140 sk_gfp_mask(sk, GFP_ATOMIC));
1134 } 1141 }
1135#endif 1142#endif
1136 1143
@@ -1146,7 +1153,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
1146 /* Clone pktoptions received with SYN, if we own the req */ 1153 /* Clone pktoptions received with SYN, if we own the req */
1147 if (ireq->pktopts) { 1154 if (ireq->pktopts) {
1148 newnp->pktoptions = skb_clone(ireq->pktopts, 1155 newnp->pktoptions = skb_clone(ireq->pktopts,
1149 sk_gfp_atomic(sk, GFP_ATOMIC)); 1156 sk_gfp_mask(sk, GFP_ATOMIC));
1150 consume_skb(ireq->pktopts); 1157 consume_skb(ireq->pktopts);
1151 ireq->pktopts = NULL; 1158 ireq->pktopts = NULL;
1152 if (newnp->pktoptions) 1159 if (newnp->pktoptions)
@@ -1212,7 +1219,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
1212 --ANK (980728) 1219 --ANK (980728)
1213 */ 1220 */
1214 if (np->rxopt.all) 1221 if (np->rxopt.all)
1215 opt_skb = skb_clone(skb, sk_gfp_atomic(sk, GFP_ATOMIC)); 1222 opt_skb = skb_clone(skb, sk_gfp_mask(sk, GFP_ATOMIC));
1216 1223
1217 if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ 1224 if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */
1218 struct dst_entry *dst = sk->sk_rx_dst; 1225 struct dst_entry *dst = sk->sk_rx_dst;
@@ -1511,7 +1518,9 @@ do_time_wait:
1511 break; 1518 break;
1512 case TCP_TW_RST: 1519 case TCP_TW_RST:
1513 tcp_v6_restore_cb(skb); 1520 tcp_v6_restore_cb(skb);
1514 goto no_tcp_socket; 1521 tcp_v6_send_reset(sk, skb);
1522 inet_twsk_deschedule_put(inet_twsk(sk));
1523 goto discard_it;
1515 case TCP_TW_SUCCESS: 1524 case TCP_TW_SUCCESS:
1516 ; 1525 ;
1517 } 1526 }
@@ -1884,6 +1893,7 @@ struct proto tcpv6_prot = {
1884 .proto_cgroup = tcp_proto_cgroup, 1893 .proto_cgroup = tcp_proto_cgroup,
1885#endif 1894#endif
1886 .clear_sk = tcp_v6_clear_sk, 1895 .clear_sk = tcp_v6_clear_sk,
1896 .diag_destroy = tcp_abort,
1887}; 1897};
1888 1898
1889static const struct inet6_protocol tcpv6_protocol = { 1899static const struct inet6_protocol tcpv6_protocol = {