Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 82b276cd authored by Hannes Frederic Sowa's avatar Hannes Frederic Sowa Committed by David S. Miller
Browse files

ipv6: protect protocols not handling ipv4 from v4 connection/bind attempts



Some ipv6 protocols cannot handle ipv4 addresses, so we must not allow
connecting and binding to them. sendmsg logic does already check msg->name
for this but must trust already connected sockets which could be set up
for connection to ipv4 address family.

Per-socket flag ipv6only is of no use here, as it is under users control
by setsockopt.

Signed-off-by: default avatarHannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 446fab59
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -783,6 +783,8 @@ int compat_ipv6_getsockopt(struct sock *sk, int level, int optname,
			   char __user *optval, int __user *optlen);

int ip6_datagram_connect(struct sock *sk, struct sockaddr *addr, int addr_len);
int ip6_datagram_connect_v6_only(struct sock *sk, struct sockaddr *addr,
				 int addr_len);

int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len,
		    int *addr_len);
+3 −0
Original line number Diff line number Diff line
@@ -320,6 +320,9 @@ static int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk,
		if (addr_len < sizeof(*addr))
			return -EINVAL;

		if (addr->sin6_family != AF_INET6)
			return -EINVAL;

		pr_debug("ping_check_bind_addr(sk=%p,addr=%pI6c,port=%d)\n",
			 sk, addr->sin6_addr.s6_addr, ntohs(addr->sin6_port));

+10 −0
Original line number Diff line number Diff line
@@ -205,6 +205,16 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
}
EXPORT_SYMBOL_GPL(ip6_datagram_connect);

int ip6_datagram_connect_v6_only(struct sock *sk, struct sockaddr *uaddr,
				 int addr_len)
{
	DECLARE_SOCKADDR(struct sockaddr_in6 *, sin6, uaddr);
	if (sin6->sin6_family != AF_INET6)
		return -EAFNOSUPPORT;
	return ip6_datagram_connect(sk, uaddr, addr_len);
}
EXPORT_SYMBOL_GPL(ip6_datagram_connect_v6_only);

void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err,
		     __be16 port, u32 info, u8 *payload)
{
+1 −1
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@ struct proto pingv6_prot = {
	.owner =	THIS_MODULE,
	.init =		ping_init_sock,
	.close =	ping_close,
	.connect =	ip6_datagram_connect,
	.connect =	ip6_datagram_connect_v6_only,
	.disconnect =	udp_disconnect,
	.setsockopt =	ipv6_setsockopt,
	.getsockopt =	ipv6_getsockopt,
+5 −1
Original line number Diff line number Diff line
@@ -250,6 +250,10 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)

	if (addr_len < SIN6_LEN_RFC2133)
		return -EINVAL;

	if (addr->sin6_family != AF_INET6)
		return -EINVAL;

	addr_type = ipv6_addr_type(&addr->sin6_addr);

	/* Raw sockets are IPv6 only */
@@ -1209,7 +1213,7 @@ struct proto rawv6_prot = {
	.owner		   = THIS_MODULE,
	.close		   = rawv6_close,
	.destroy	   = raw6_destroy,
	.connect	   = ip6_datagram_connect,
	.connect	   = ip6_datagram_connect_v6_only,
	.disconnect	   = udp_disconnect,
	.ioctl		   = rawv6_ioctl,
	.init		   = rawv6_init_sk,
Loading