@@ -927,6 +927,7 @@ static int ip6_dst_lookup_tail(struct sock *sk,
{
int err;
struct net *net = sock_net(sk);
+ struct net_device *dev_out;
if (*dst == NULL)
*dst = ip6_route_output(net, sk, fl);
@@ -934,6 +935,32 @@ static int ip6_dst_lookup_tail(struct sock *sk,
if ((err = (*dst)->error))
goto out_err_release;
+ dev_out = ip6_dst_idev(*dst)->dev;
+ if (dev_out && ipv6_addr_loopback(&fl->fl6_src) &&
+ !(dev_out->flags & IFF_LOOPBACK)) {
+ /*
+ * If socket is bound to loopback address but interface
+ * is not then it is invalid...
+ */
+ struct inet6_ifaddr *ifa;
+ struct inet6_dev *idev = in6_dev_get(dev_out);
+ err = -EINVAL;
+ if (idev) {
+ list_for_each_entry(ifa, &idev->addr_list, if_list)
+ {
+ /*
+ * ... unless the interface has the same address
+ */
+ if (ipv6_addr_equal(&ifa->addr, &fl->fl6_dst))
+ err = 0;
+ }
+ in6_dev_put(idev);
+ }
+
+ if (err)
+ goto out_err_release;
+ }
+
if (ipv6_addr_any(&fl->fl6_src)) {
err = ipv6_dev_get_saddr(net, ip6_dst_idev(*dst)->dev,
&fl->fl6_dst,