diff options
Diffstat (limited to 'net/ipv4/af_inet.c')
-rw-r--r-- | net/ipv4/af_inet.c | 17 |
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), |