Signed-off-by: Hannes Frederic Sowa <han...@stressinduktion.org>
---
 drivers/target/iscsi/cxgbit/cxgbit_cm.c |  2 +-
 include/linux/inetdevice.h              |  5 +++--
 include/net/route.h                     | 10 ++++++----
 net/ipv4/devinet.c                      | 19 ++++++++++++++++---
 net/ipv4/icmp.c                         |  4 ++--
 net/ipv4/igmp.c                         |  2 +-
 net/ipv4/route.c                        | 21 ++++++++++++---------
 net/ipv4/xfrm4_policy.c                 |  2 +-
 net/sctp/protocol.c                     |  4 ++--
 net/tipc/udp_media.c                    |  2 +-
 10 files changed, 45 insertions(+), 26 deletions(-)

diff --git a/drivers/target/iscsi/cxgbit/cxgbit_cm.c 
b/drivers/target/iscsi/cxgbit/cxgbit_cm.c
index 37a05185dcbe0e..4ae59d20d8e260 100644
--- a/drivers/target/iscsi/cxgbit/cxgbit_cm.c
+++ b/drivers/target/iscsi/cxgbit/cxgbit_cm.c
@@ -266,7 +266,7 @@ static struct net_device *cxgbit_ipv4_netdev(__be32 saddr)
 {
        struct net_device *ndev;
 
-       ndev = __ip_dev_find(&init_net, saddr, false);
+       ndev = __ip_dev_find(&init_net, NULL, saddr, false);
        if (!ndev)
                return NULL;
 
diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
index a41bfce099e0a1..9411270cb0fe64 100644
--- a/include/linux/inetdevice.h
+++ b/include/linux/inetdevice.h
@@ -160,10 +160,11 @@ void inet_netconf_notify_devconf(struct net *net, int 
type, int ifindex,
                                 struct ipv4_devconf *devconf);
 
 struct in_ifaddr *ifa_find_rcu(struct net *net, __be32 addr);
-struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref);
+struct net_device *__ip_dev_find(struct net *net, struct afnetns *afnetns,
+                                __be32 addr, bool devref);
 static inline struct net_device *ip_dev_find(struct net *net, __be32 addr)
 {
-       return __ip_dev_find(net, addr, true);
+       return __ip_dev_find(net, NULL, addr, true);
 }
 
 int inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b);
diff --git a/include/net/route.h b/include/net/route.h
index c0874c87c17371..d29449d1863636 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -113,13 +113,15 @@ struct in_device;
 int ip_rt_init(void);
 void rt_cache_flush(struct net *net);
 void rt_flush_dev(struct net_device *dev);
-struct rtable *__ip_route_output_key_hash(struct net *, struct flowi4 *flp,
-                                         int mp_hash);
+struct rtable *__ip_route_output_key_hash(struct net *net,
+                                         struct afnetns *afnetns,
+                                         struct flowi4 *flp, int mp_hash);
 
 static inline struct rtable *__ip_route_output_key(struct net *net,
+                                                  struct afnetns *afnetns,
                                                   struct flowi4 *flp)
 {
-       return __ip_route_output_key_hash(net, flp, -1);
+       return __ip_route_output_key_hash(net, afnetns, flp, -1);
 }
 
 struct rtable *ip_route_output_flow(struct net *, struct flowi4 *flp,
@@ -286,7 +288,7 @@ static inline struct rtable *ip_route_connect(struct flowi4 
*fl4,
                              sport, dport, sk);
 
        if (!dst || !src) {
-               rt = __ip_route_output_key(net, fl4);
+               rt = __ip_route_output_key(net, NULL, fl4);
                if (IS_ERR(rt))
                        return rt;
                ip_rt_put(rt);
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 0844d917aa8d7d..82a7389ec86faa 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -150,14 +150,27 @@ struct in_ifaddr *ifa_find_rcu(struct net *net, __be32 
addr)
  *
  * If a caller uses devref=false, it should be protected by RCU, or RTNL
  */
-struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref)
+struct net_device *__ip_dev_find(struct net *net, struct afnetns *afnetns,
+                                __be32 addr, bool devref)
 {
-       struct net_device *result;
+       struct net_device *result = NULL;
        struct in_ifaddr *ifa;
 
        rcu_read_lock();
        ifa = ifa_find_rcu(net, addr);
-       result = ifa ? ifa->ifa_dev->dev : NULL;
+#if IS_ENABLED(CONFIG_AFNETNS)
+       if (afnetns && afnetns != net->afnet_ns) {
+               /* we are in a child namespace, thus only allow to
+                * explicitly configured addresses
+                */
+               if (!ifa || ifa->afnetns != afnetns) {
+                       rcu_read_unlock();
+                       return NULL;
+               }
+       }
+#endif
+       if (ifa)
+               result = ifa->ifa_dev->dev;
        if (!result) {
                struct flowi4 fl4 = { .daddr = addr };
                struct fib_result res = { 0 };
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index fc310db2708bf6..74261d6b86e4fc 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -505,7 +505,7 @@ static struct rtable *icmp_route_lookup(struct net *net,
        fl4->flowi4_oif = l3mdev_master_ifindex(skb_dst(skb_in)->dev);
 
        security_skb_classify_flow(skb_in, flowi4_to_flowi(fl4));
-       rt = __ip_route_output_key_hash(net, fl4,
+       rt = __ip_route_output_key_hash(net, NULL, fl4,
                                        icmp_multipath_hash_skb(skb_in));
        if (IS_ERR(rt))
                return rt;
@@ -529,7 +529,7 @@ static struct rtable *icmp_route_lookup(struct net *net,
 
        if (inet_addr_type_dev_table(net, skb_dst(skb_in)->dev,
                                     fl4_dec.saddr) == RTN_LOCAL) {
-               rt2 = __ip_route_output_key(net, &fl4_dec);
+               rt2 = __ip_route_output_key(net, NULL, &fl4_dec);
                if (IS_ERR(rt2))
                        err = PTR_ERR(rt2);
        } else {
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 44fd86de2823dd..d246bf1704f4d8 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -1754,7 +1754,7 @@ static struct in_device *ip_mc_find_dev(struct net *net, 
struct ip_mreqn *imr)
                return idev;
        }
        if (imr->imr_address.s_addr) {
-               dev = __ip_dev_find(net, imr->imr_address.s_addr, false);
+               dev = __ip_dev_find(net, NULL, imr->imr_address.s_addr, false);
                if (!dev)
                        return NULL;
        }
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 8471dd11677146..f3304647082182 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1045,7 +1045,7 @@ void ipv4_update_pmtu(struct sk_buff *skb, struct net 
*net, u32 mtu,
 
        __build_flow_key(net, &fl4, NULL, iph, oif,
                         RT_TOS(iph->tos), protocol, mark, flow_flags);
-       rt = __ip_route_output_key(net, &fl4);
+       rt = __ip_route_output_key(net, NULL, &fl4);
        if (!IS_ERR(rt)) {
                __ip_rt_update_pmtu(rt, &fl4, mtu);
                ip_rt_put(rt);
@@ -1064,7 +1064,7 @@ static void __ipv4_sk_update_pmtu(struct sk_buff *skb, 
struct sock *sk, u32 mtu)
        if (!fl4.flowi4_mark)
                fl4.flowi4_mark = IP4_REPLY_MARK(sock_net(sk), skb->mark);
 
-       rt = __ip_route_output_key(sock_net(sk), &fl4);
+       rt = __ip_route_output_key(sock_net(sk), NULL, &fl4);
        if (!IS_ERR(rt)) {
                __ip_rt_update_pmtu(rt, &fl4, mtu);
                ip_rt_put(rt);
@@ -1134,7 +1134,7 @@ void ipv4_redirect(struct sk_buff *skb, struct net *net,
 
        __build_flow_key(net, &fl4, NULL, iph, oif,
                         RT_TOS(iph->tos), protocol, mark, flow_flags);
-       rt = __ip_route_output_key(net, &fl4);
+       rt = __ip_route_output_key(net, NULL, &fl4);
        if (!IS_ERR(rt)) {
                __ip_do_redirect(rt, skb, &fl4, false);
                ip_rt_put(rt);
@@ -1150,7 +1150,7 @@ void ipv4_sk_redirect(struct sk_buff *skb, struct sock 
*sk)
        struct net *net = sock_net(sk);
 
        __build_flow_key(net, &fl4, sk, iph, 0, 0, 0, 0, 0);
-       rt = __ip_route_output_key(net, &fl4);
+       rt = __ip_route_output_key(net, NULL, &fl4);
        if (!IS_ERR(rt)) {
                __ip_do_redirect(rt, skb, &fl4, false);
                ip_rt_put(rt);
@@ -2202,8 +2202,9 @@ static struct rtable *__mkroute_output(const struct 
fib_result *res,
  * Major route resolver routine.
  */
 
-struct rtable *__ip_route_output_key_hash(struct net *net, struct flowi4 *fl4,
-                                         int mp_hash)
+struct rtable *__ip_route_output_key_hash(struct net *net,
+                                         struct afnetns *afnetns,
+                                         struct flowi4 *fl4, int mp_hash)
 {
        struct net_device *dev_out = NULL;
        __u8 tos = RT_FL_TOS(fl4);
@@ -2244,7 +2245,7 @@ struct rtable *__ip_route_output_key_hash(struct net 
*net, struct flowi4 *fl4,
                    (ipv4_is_multicast(fl4->daddr) ||
                     ipv4_is_lbcast(fl4->daddr))) {
                        /* It is equivalent to inet_addr_type(saddr) == 
RTN_LOCAL */
-                       dev_out = __ip_dev_find(net, fl4->saddr, false);
+                       dev_out = __ip_dev_find(net, NULL, fl4->saddr, false);
                        if (!dev_out)
                                goto out;
 
@@ -2269,7 +2270,7 @@ struct rtable *__ip_route_output_key_hash(struct net 
*net, struct flowi4 *fl4,
 
                if (!(fl4->flowi4_flags & FLOWI_FLAG_ANYSRC)) {
                        /* It is equivalent to inet_addr_type(saddr) == 
RTN_LOCAL */
-                       if (!__ip_dev_find(net, fl4->saddr, false))
+                       if (!__ip_dev_find(net, afnetns, fl4->saddr, false))
                                goto out;
                }
        }
@@ -2458,7 +2459,9 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, 
struct dst_entry *dst_or
 struct rtable *ip_route_output_flow(struct net *net, struct flowi4 *flp4,
                                    const struct sock *sk)
 {
-       struct rtable *rt = __ip_route_output_key(net, flp4);
+       struct rtable *rt;
+
+       rt = __ip_route_output_key(net, sk ? sock_afnetns(sk) : NULL, flp4);
 
        if (IS_ERR(rt))
                return rt;
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 71b4ecc195c707..c8d9eaa59be8fc 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -33,7 +33,7 @@ static struct dst_entry *__xfrm4_dst_lookup(struct net *net, 
struct flowi4 *fl4,
 
        fl4->flowi4_flags = FLOWI_FLAG_SKIP_NH_OIF;
 
-       rt = __ip_route_output_key(net, fl4);
+       rt = __ip_route_output_key(net, NULL, fl4);
        if (!IS_ERR(rt))
                return &rt->dst;
 
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 1b6d4574d2b02a..cd77ec87c5f9ef 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -520,8 +520,8 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union 
sctp_addr *saddr,
                /* Ensure the src address belongs to the output
                 * interface.
                 */
-               odev = __ip_dev_find(sock_net(sk), laddr->a.v4.sin_addr.s_addr,
-                                    false);
+               odev = __ip_dev_find(sock_net(sk), NULL,
+                                    laddr->a.v4.sin_addr.s_addr, false);
                if (!odev || odev->ifindex != fl4->flowi4_oif) {
                        if (&rt->dst != dst)
                                dst_release(&rt->dst);
diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c
index 46061cf48cd135..98bc29e63058a2 100644
--- a/net/tipc/udp_media.c
+++ b/net/tipc/udp_media.c
@@ -688,7 +688,7 @@ static int tipc_udp_enable(struct net *net, struct 
tipc_bearer *b,
        if (local.proto == htons(ETH_P_IP)) {
                struct net_device *dev;
 
-               dev = __ip_dev_find(net, local.ipv4.s_addr, false);
+               dev = __ip_dev_find(net, NULL, local.ipv4.s_addr, false);
                if (!dev) {
                        err = -ENODEV;
                        goto err;
-- 
2.9.3

Reply via email to