lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20170312230151.5185-6-hannes@stressinduktion.org>
Date:   Mon, 13 Mar 2017 00:01:29 +0100
From:   Hannes Frederic Sowa <hannes@...essinduktion.org>
To:     netdev@...r.kernel.org
Subject: [PATCH net-next RFC v1 05/27] afnetns: ipv6 integration

Like the previous IPv4 counterpart, this patch associates every IPv6
address with a corresponding afnet namespace. The namespace can be set
via file descriptor and the inode gets reported during dumping.

Signed-off-by: Hannes Frederic Sowa <hannes@...essinduktion.org>
---
 include/net/if_inet6.h |  3 +++
 net/core/afnetns.c     |  3 +++
 net/ipv6/addrconf.c    | 70 +++++++++++++++++++++++++++++++++++++++++---------
 3 files changed, 64 insertions(+), 12 deletions(-)

diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h
index f656f9051acafa..cad645851501f4 100644
--- a/include/net/if_inet6.h
+++ b/include/net/if_inet6.h
@@ -41,6 +41,9 @@ enum {
 struct inet6_ifaddr {
 	struct in6_addr		addr;
 	__u32			prefix_len;
+#if IS_ENABLED(CONFIG_AFNETNS)
+	struct afnetns		*afnetns;
+#endif
 
 	/* In seconds, relative to tstamp. Expiry is at tstamp + HZ * lft. */
 	__u32			valid_lft;
diff --git a/net/core/afnetns.c b/net/core/afnetns.c
index 12b823ae780796..b96c25b5ebe30d 100644
--- a/net/core/afnetns.c
+++ b/net/core/afnetns.c
@@ -56,6 +56,7 @@ void afnetns_free(struct afnetns *afnetns)
 	put_net(afnetns->net);
 	kfree(afnetns);
 }
+EXPORT_SYMBOL(afnetns_free);
 
 struct afnetns *afnetns_get_by_fd(int fd)
 {
@@ -76,11 +77,13 @@ struct afnetns *afnetns_get_by_fd(int fd)
 	fput(file);
 	return afnetns;
 }
+EXPORT_SYMBOL(afnetns_get_by_fd);
 
 unsigned int afnetns_to_inode(struct afnetns *afnetns)
 {
 	return afnetns->ns.inum;
 }
+EXPORT_SYMBOL(afnetns_to_inode);
 
 struct afnetns *copy_afnet_ns(unsigned long flags, struct nsproxy *old)
 {
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 8c69768a5c4606..c67f6d3c5b9a7a 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -910,7 +910,9 @@ void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp)
 		return;
 	}
 	ip6_rt_put(ifp->rt);
-
+#if IS_ENABLED(CONFIG_AFNETNS)
+	afnetns_put(ifp->afnetns);
+#endif
 	kfree_rcu(ifp, rcu);
 }
 
@@ -942,9 +944,10 @@ static u32 inet6_addr_hash(const struct in6_addr *addr)
 /* On success it returns ifp with increased reference count */
 
 static struct inet6_ifaddr *
-ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
-	      const struct in6_addr *peer_addr, int pfxlen,
-	      int scope, u32 flags, u32 valid_lft, u32 prefered_lft)
+__ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
+		const struct in6_addr *peer_addr, int pfxlen,
+		int scope, u32 flags, u32 valid_lft, u32 prefered_lft,
+		struct afnetns *afnetns)
 {
 	struct net *net = dev_net(idev->dev);
 	struct inet6_ifaddr *ifa = NULL;
@@ -1002,7 +1005,9 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
 	ifa->addr = *addr;
 	if (peer_addr)
 		ifa->peer_addr = *peer_addr;
-
+#if IS_ENABLED(CONFIG_AFNETNS)
+	ifa->afnetns = afnetns_get(afnetns);
+#endif
 	spin_lock_init(&ifa->lock);
 	INIT_DELAYED_WORK(&ifa->dad_work, addrconf_dad_work);
 	INIT_HLIST_NODE(&ifa->addr_lst);
@@ -1054,6 +1059,17 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
 	goto out2;
 }
 
+static struct inet6_ifaddr *ipv6_add_addr(struct inet6_dev *idev,
+					  const struct in6_addr *addr,
+					  const struct in6_addr *peer_addr,
+					  int pfxlen, int scope, u32 flags,
+					  u32 valid_lft, u32 prefered_lft)
+{
+	return __ipv6_add_addr(idev, addr, peer_addr, pfxlen, scope, flags,
+			       valid_lft, prefered_lft,
+			       net_afnetns(dev_net(idev->dev)));
+}
+
 enum cleanup_prefix_rt_t {
 	CLEANUP_PREFIX_RT_NOP,    /* no cleanup action for prefix route */
 	CLEANUP_PREFIX_RT_DEL,    /* delete the prefix route */
@@ -2741,7 +2757,8 @@ static int inet6_addr_add(struct net *net, int ifindex,
 			  const struct in6_addr *pfx,
 			  const struct in6_addr *peer_pfx,
 			  unsigned int plen, __u32 ifa_flags,
-			  __u32 prefered_lft, __u32 valid_lft)
+			  __u32 prefered_lft, __u32 valid_lft,
+			  struct afnetns *afnetns)
 {
 	struct inet6_ifaddr *ifp;
 	struct inet6_dev *idev;
@@ -2799,8 +2816,8 @@ static int inet6_addr_add(struct net *net, int ifindex,
 		prefered_lft = timeout;
 	}
 
-	ifp = ipv6_add_addr(idev, pfx, peer_pfx, plen, scope, ifa_flags,
-			    valid_lft, prefered_lft);
+	ifp = __ipv6_add_addr(idev, pfx, peer_pfx, plen, scope, ifa_flags,
+			      valid_lft, prefered_lft, afnetns);
 
 	if (!IS_ERR(ifp)) {
 		if (!(ifa_flags & IFA_F_NOPREFIXROUTE)) {
@@ -2885,7 +2902,8 @@ int addrconf_add_ifaddr(struct net *net, void __user *arg)
 	rtnl_lock();
 	err = inet6_addr_add(net, ireq.ifr6_ifindex, &ireq.ifr6_addr, NULL,
 			     ireq.ifr6_prefixlen, IFA_F_PERMANENT,
-			     INFINITY_LIFE_TIME, INFINITY_LIFE_TIME);
+			     INFINITY_LIFE_TIME, INFINITY_LIFE_TIME,
+			     net_afnetns(net));
 	rtnl_unlock();
 	return err;
 }
@@ -4502,6 +4520,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh)
 	struct nlattr *tb[IFA_MAX+1];
 	struct in6_addr *pfx, *peer_pfx;
 	struct inet6_ifaddr *ifa;
+	struct afnetns *afnetns = NULL;
 	struct net_device *dev;
 	u32 valid_lft = INFINITY_LIFE_TIME, preferred_lft = INFINITY_LIFE_TIME;
 	u32 ifa_flags;
@@ -4537,15 +4556,31 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh)
 	ifa_flags &= IFA_F_NODAD | IFA_F_HOMEADDRESS | IFA_F_MANAGETEMPADDR |
 		     IFA_F_NOPREFIXROUTE | IFA_F_MCAUTOJOIN;
 
+#if IS_ENABLED(CONFIG_AFNETNS)
+	if (tb[IFA_AFNETNS_FD]) {
+		int fd = nla_get_s32(tb[IFA_AFNETNS_FD]);
+
+		afnetns = afnetns_get_by_fd(fd);
+		if (IS_ERR(afnetns))
+			return PTR_ERR(afnetns);
+	} else {
+		afnetns = afnetns_get(net_afnetns(net));
+	}
+#else
+	if (tb[IFA_AFNETNS_FD])
+		return -EOPNOTSUPP;
+#endif
+
 	ifa = ipv6_get_ifaddr(net, pfx, dev, 1);
 	if (!ifa) {
 		/*
 		 * It would be best to check for !NLM_F_CREATE here but
 		 * userspace already relies on not having to provide this.
 		 */
-		return inet6_addr_add(net, ifm->ifa_index, pfx, peer_pfx,
+		err =  inet6_addr_add(net, ifm->ifa_index, pfx, peer_pfx,
 				      ifm->ifa_prefixlen, ifa_flags,
-				      preferred_lft, valid_lft);
+				      preferred_lft, valid_lft, afnetns);
+		goto out;
 	}
 
 	if (nlh->nlmsg_flags & NLM_F_EXCL ||
@@ -4555,6 +4590,10 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh)
 		err = inet6_addr_modify(ifa, ifa_flags, preferred_lft, valid_lft);
 
 	in6_ifa_put(ifa);
+out:
+#if IS_ENABLED(CONFIG_AFNETNS)
+	afnetns_put(afnetns);
+#endif
 
 	return err;
 }
@@ -4603,7 +4642,8 @@ static inline int inet6_ifaddr_msgsize(void)
 	       + nla_total_size(16) /* IFA_LOCAL */
 	       + nla_total_size(16) /* IFA_ADDRESS */
 	       + nla_total_size(sizeof(struct ifa_cacheinfo))
-	       + nla_total_size(4)  /* IFA_FLAGS */;
+	       + nla_total_size(4)  /* IFA_FLAGS */
+	       + nla_total_size(4); /* IFA_AFNETNS_INODE */
 }
 
 static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
@@ -4655,6 +4695,12 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
 	if (nla_put_u32(skb, IFA_FLAGS, ifa->flags) < 0)
 		goto error;
 
+#if IS_ENABLED(CONFIG_AFNETNS)
+	if (nla_put_u32(skb, IFA_AFNETNS_INODE,
+			afnetns_to_inode(ifa->afnetns)))
+		goto error;
+#endif
+
 	nlmsg_end(skb, nlh);
 	return 0;
 
-- 
2.9.3

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ