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

Commit 187e3838 authored by YOSHIFUJI Hideaki's avatar YOSHIFUJI Hideaki
Browse files

[IPV6]: Check outgoing interface even if source address is unspecified.



The outgoing interface index (ipi6_ifindex) in IPV6_PKTINFO
ancillary data, is not checked if the source address (ipi6_addr)
is unspecified.  If the ipi6_ifindex is the not-exist interface,
it should be fail.

Based on patch from Shan Wei <shanwei@cn.fujitsu.com> and
Brian Haley <brian.haley@hp.com>.

Signed-off-by: default avatarShan Wei <shanwei@cn.fujitsu.com>
Signed-off-by: default avatarBrian Haley <brian.haley@hp.com>
Signed-off-by: default avatarYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
parent 95b496b6
Loading
Loading
Loading
Loading
+22 −20
Original line number Diff line number Diff line
@@ -509,7 +509,6 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,

	for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
		int addr_type;
		struct net_device *dev = NULL;

		if (!CMSG_OK(msg, cmsg)) {
			err = -EINVAL;
@@ -522,6 +521,9 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
		switch (cmsg->cmsg_type) {
		case IPV6_PKTINFO:
		case IPV6_2292PKTINFO:
		    {
			struct net_device *dev = NULL;

			if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct in6_pktinfo))) {
				err = -EINVAL;
				goto exit_f;
@@ -535,32 +537,32 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
				fl->oif = src_info->ipi6_ifindex;
			}

			addr_type = ipv6_addr_type(&src_info->ipi6_addr);

			if (addr_type == IPV6_ADDR_ANY)
				break;
			addr_type = __ipv6_addr_type(&src_info->ipi6_addr);

			if (addr_type & IPV6_ADDR_LINKLOCAL) {
				if (!src_info->ipi6_ifindex)
					return -EINVAL;
				else {
					dev = dev_get_by_index(&init_net, src_info->ipi6_ifindex);
			if (fl->oif) {
				dev = dev_get_by_index(&init_net, fl->oif);
				if (!dev)
					return -ENODEV;
				}
			}
			} else if (addr_type & IPV6_ADDR_LINKLOCAL)
				return -EINVAL;

			if (addr_type != IPV6_ADDR_ANY) {
				int strict = __ipv6_addr_src_scope(addr_type) <= IPV6_ADDR_SCOPE_LINKLOCAL;
				if (!ipv6_chk_addr(&init_net, &src_info->ipi6_addr,
					   dev, 0)) {
				if (dev)
					dev_put(dev);
						   strict ? dev : NULL, 0))
					err = -EINVAL;
				goto exit_f;
				else
					ipv6_addr_copy(&fl->fl6_src, &src_info->ipi6_addr);
			}

			if (dev)
				dev_put(dev);

			ipv6_addr_copy(&fl->fl6_src, &src_info->ipi6_addr);
			if (err)
				goto exit_f;

			break;
		    }

		case IPV6_FLOWINFO:
			if (cmsg->cmsg_len < CMSG_LEN(4)) {