Skip to content

Commit 2f987a7

Browse files
Paolo Abenidavem330
authored andcommitted
net: ipv6: keep sk status consistent after datagram connect failure
On unsuccesful ip6_datagram_connect(), if the failure is caused by ip6_datagram_dst_update(), the sk peer information are cleared, but the sk->sk_state is preserved. If the socket was already in an established status, the overall sk status is inconsistent and fouls later checks in datagram code. Fix this saving the old peer information and restoring them in case of failure. This also aligns ipv6 datagram connect() behavior with ipv4. v1 -> v2: - added missing Fixes tag Fixes: 85cb73f ("net: ipv6: reset daddr and dport in sk if connect() fails") Signed-off-by: Paolo Abeni <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent b747594 commit 2f987a7

File tree

1 file changed

+14
-7
lines changed

1 file changed

+14
-7
lines changed

net/ipv6/datagram.c

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,12 @@ int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr,
146146
struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr;
147147
struct inet_sock *inet = inet_sk(sk);
148148
struct ipv6_pinfo *np = inet6_sk(sk);
149-
struct in6_addr *daddr;
149+
struct in6_addr *daddr, old_daddr;
150+
__be32 fl6_flowlabel = 0;
151+
__be32 old_fl6_flowlabel;
152+
__be32 old_dport;
150153
int addr_type;
151154
int err;
152-
__be32 fl6_flowlabel = 0;
153155

154156
if (usin->sin6_family == AF_INET) {
155157
if (__ipv6_only_sock(sk))
@@ -238,9 +240,13 @@ int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr,
238240
}
239241
}
240242

243+
/* save the current peer information before updating it */
244+
old_daddr = sk->sk_v6_daddr;
245+
old_fl6_flowlabel = np->flow_label;
246+
old_dport = inet->inet_dport;
247+
241248
sk->sk_v6_daddr = *daddr;
242249
np->flow_label = fl6_flowlabel;
243-
244250
inet->inet_dport = usin->sin6_port;
245251

246252
/*
@@ -250,11 +256,12 @@ int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr,
250256

251257
err = ip6_datagram_dst_update(sk, true);
252258
if (err) {
253-
/* Reset daddr and dport so that udp_v6_early_demux()
254-
* fails to find this socket
259+
/* Restore the socket peer info, to keep it consistent with
260+
* the old socket state
255261
*/
256-
memset(&sk->sk_v6_daddr, 0, sizeof(sk->sk_v6_daddr));
257-
inet->inet_dport = 0;
262+
sk->sk_v6_daddr = old_daddr;
263+
np->flow_label = old_fl6_flowlabel;
264+
inet->inet_dport = old_dport;
258265
goto out;
259266
}
260267

0 commit comments

Comments
 (0)