@@ -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;
@@ -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);
@@ -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);
@@ -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 };
@@ -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 {
@@ -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;
}
@@ -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;
@@ -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;
@@ -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);
@@ -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;
Signed-off-by: Hannes Frederic Sowa <hannes@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(-)