Commit 3eef54d7 authored by Ville Nuorvala's avatar Ville Nuorvala Committed by David S. Miller

[IPV6]: Fix refcount leaks in udpv6_connect().

parent 431aa1db
...@@ -299,9 +299,10 @@ int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) ...@@ -299,9 +299,10 @@ int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
if (addr_type == IPV6_ADDR_MAPPED) { if (addr_type == IPV6_ADDR_MAPPED) {
struct sockaddr_in sin; struct sockaddr_in sin;
if (__ipv6_only_sock(sk)) if (__ipv6_only_sock(sk)) {
return -ENETUNREACH; err = -ENETUNREACH;
goto out;
}
sin.sin_family = AF_INET; sin.sin_family = AF_INET;
sin.sin_addr.s_addr = daddr->s6_addr32[3]; sin.sin_addr.s_addr = daddr->s6_addr32[3];
sin.sin_port = usin->sin6_port; sin.sin_port = usin->sin6_port;
...@@ -309,8 +310,8 @@ int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) ...@@ -309,8 +310,8 @@ int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
err = udp_connect(sk, (struct sockaddr*) &sin, sizeof(sin)); err = udp_connect(sk, (struct sockaddr*) &sin, sizeof(sin));
ipv4_connected: ipv4_connected:
if (err < 0) if (err)
return err; goto out;
ipv6_addr_set(&np->daddr, 0, 0, htonl(0x0000ffff), inet->daddr); ipv6_addr_set(&np->daddr, 0, 0, htonl(0x0000ffff), inet->daddr);
...@@ -323,7 +324,7 @@ int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) ...@@ -323,7 +324,7 @@ int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
ipv6_addr_set(&np->rcv_saddr, 0, 0, htonl(0x0000ffff), ipv6_addr_set(&np->rcv_saddr, 0, 0, htonl(0x0000ffff),
inet->rcv_saddr); inet->rcv_saddr);
} }
return 0; goto out;
} }
if (addr_type&IPV6_ADDR_LINKLOCAL) { if (addr_type&IPV6_ADDR_LINKLOCAL) {
...@@ -331,8 +332,8 @@ int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) ...@@ -331,8 +332,8 @@ int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
usin->sin6_scope_id) { usin->sin6_scope_id) {
if (sk->sk_bound_dev_if && if (sk->sk_bound_dev_if &&
sk->sk_bound_dev_if != usin->sin6_scope_id) { sk->sk_bound_dev_if != usin->sin6_scope_id) {
fl6_sock_release(flowlabel); err = -EINVAL;
return -EINVAL; goto out;
} }
sk->sk_bound_dev_if = usin->sin6_scope_id; sk->sk_bound_dev_if = usin->sin6_scope_id;
if (!sk->sk_bound_dev_if && if (!sk->sk_bound_dev_if &&
...@@ -341,8 +342,10 @@ int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) ...@@ -341,8 +342,10 @@ int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
} }
/* Connect to link-local address requires an interface */ /* Connect to link-local address requires an interface */
if (!sk->sk_bound_dev_if) if (!sk->sk_bound_dev_if) {
return -EINVAL; err = -EINVAL;
goto out;
}
} }
ipv6_addr_copy(&np->daddr, daddr); ipv6_addr_copy(&np->daddr, daddr);
...@@ -379,31 +382,33 @@ int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) ...@@ -379,31 +382,33 @@ int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
if ((err = dst->error) != 0) { if ((err = dst->error) != 0) {
dst_release(dst); dst_release(dst);
fl6_sock_release(flowlabel); goto out;
return err;
} }
/* get the source address used in the appropriate device */ /* get the source address used in the appropriate device */
err = ipv6_get_saddr(dst, daddr, &fl.fl6_src); err = ipv6_get_saddr(dst, daddr, &fl.fl6_src);
if (err == 0) { if (err) {
if (ipv6_addr_any(&np->saddr)) dst_release(dst);
ipv6_addr_copy(&np->saddr, &fl.fl6_src); goto out;
}
if (ipv6_addr_any(&np->rcv_saddr)) {
ipv6_addr_copy(&np->rcv_saddr, &fl.fl6_src);
inet->rcv_saddr = LOOPBACK4_IPV6;
}
ip6_dst_store(sk, dst, if (ipv6_addr_any(&np->saddr))
!ipv6_addr_cmp(&fl.fl6_dst, &np->daddr) ? ipv6_addr_copy(&np->saddr, &fl.fl6_src);
&np->daddr : NULL);
sk->sk_state = TCP_ESTABLISHED; if (ipv6_addr_any(&np->rcv_saddr)) {
ipv6_addr_copy(&np->rcv_saddr, &fl.fl6_src);
inet->rcv_saddr = LOOPBACK4_IPV6;
} }
fl6_sock_release(flowlabel);
ip6_dst_store(sk, dst,
!ipv6_addr_cmp(&fl.fl6_dst, &np->daddr) ?
&np->daddr : NULL);
sk->sk_state = TCP_ESTABLISHED;
out:
fl6_sock_release(flowlabel);
return err; return err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment