aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/af_inet.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/af_inet.c')
-rw-r--r--net/ipv4/af_inet.c17
1 files changed, 12 insertions, 5 deletions
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 0413af3e2285..963a621e75c7 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -153,7 +153,7 @@ void inet_sock_destruct(struct sock *sk)
153 WARN_ON(sk->sk_wmem_queued); 153 WARN_ON(sk->sk_wmem_queued);
154 WARN_ON(sk->sk_forward_alloc); 154 WARN_ON(sk->sk_forward_alloc);
155 155
156 kfree(inet->opt); 156 kfree(rcu_dereference_protected(inet->inet_opt, 1));
157 dst_release(rcu_dereference_check(sk->sk_dst_cache, 1)); 157 dst_release(rcu_dereference_check(sk->sk_dst_cache, 1));
158 sk_refcnt_debug_dec(sk); 158 sk_refcnt_debug_dec(sk);
159} 159}
@@ -1106,9 +1106,12 @@ static int inet_sk_reselect_saddr(struct sock *sk)
1106 struct flowi4 fl4; 1106 struct flowi4 fl4;
1107 struct rtable *rt; 1107 struct rtable *rt;
1108 __be32 new_saddr; 1108 __be32 new_saddr;
1109 struct ip_options_rcu *inet_opt;
1109 1110
1110 if (inet->opt && inet->opt->srr) 1111 inet_opt = rcu_dereference_protected(inet->inet_opt,
1111 daddr = inet->opt->faddr; 1112 sock_owned_by_user(sk));
1113 if (inet_opt && inet_opt->opt.srr)
1114 daddr = inet_opt->opt.faddr;
1112 1115
1113 /* Query new route. */ 1116 /* Query new route. */
1114 rt = ip_route_connect(&fl4, daddr, 0, RT_CONN_FLAGS(sk), 1117 rt = ip_route_connect(&fl4, daddr, 0, RT_CONN_FLAGS(sk),
@@ -1148,6 +1151,7 @@ int inet_sk_rebuild_header(struct sock *sk)
1148 struct inet_sock *inet = inet_sk(sk); 1151 struct inet_sock *inet = inet_sk(sk);
1149 struct rtable *rt = (struct rtable *)__sk_dst_check(sk, 0); 1152 struct rtable *rt = (struct rtable *)__sk_dst_check(sk, 0);
1150 __be32 daddr; 1153 __be32 daddr;
1154 struct ip_options_rcu *inet_opt;
1151 int err; 1155 int err;
1152 1156
1153 /* Route is OK, nothing to do. */ 1157 /* Route is OK, nothing to do. */
@@ -1155,9 +1159,12 @@ int inet_sk_rebuild_header(struct sock *sk)
1155 return 0; 1159 return 0;
1156 1160
1157 /* Reroute. */ 1161 /* Reroute. */
1162 rcu_read_lock();
1163 inet_opt = rcu_dereference(inet->inet_opt);
1158 daddr = inet->inet_daddr; 1164 daddr = inet->inet_daddr;
1159 if (inet->opt && inet->opt->srr) 1165 if (inet_opt && inet_opt->opt.srr)
1160 daddr = inet->opt->faddr; 1166 daddr = inet_opt->opt.faddr;
1167 rcu_read_unlock();
1161 rt = ip_route_output_ports(sock_net(sk), sk, daddr, inet->inet_saddr, 1168 rt = ip_route_output_ports(sock_net(sk), sk, daddr, inet->inet_saddr,
1162 inet->inet_dport, inet->inet_sport, 1169 inet->inet_dport, inet->inet_sport,
1163 sk->sk_protocol, RT_CONN_FLAGS(sk), 1170 sk->sk_protocol, RT_CONN_FLAGS(sk),