[RFC] [patch 4/6] [Network namespace] Network inet devices isolation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The network isolation relies on the fact that an application can not
use IP addresses not belonging to the container in which it's
running. This patch isolates the inet device level by adding a
structure namespace pointer in the structure in_ifaddr. When an ip
address is set inside a network namespace, the structure in_ifaddr is
filled with the current namespace pointer. There is a special case
with loopback address which belongs to all the namespaces and its
particularity is to have the network namespace pointer set to NULL.
This patch isolates the ifconfig, ip addr commands, so when an IP
address is set, this one it is not visible by another network
namespaces.

Replace-Subject: [Network namespace] Network inet devices isolation 
Signed-off-by: Daniel Lezcano <[email protected]> 
--
 include/linux/inetdevice.h |    1 +
 net/ipv4/devinet.c         |   28 +++++++++++++++++++++++++++-
 2 files changed, 28 insertions(+), 1 deletion(-)

Index: 2.6-mm/include/linux/inetdevice.h
===================================================================
--- 2.6-mm.orig/include/linux/inetdevice.h
+++ 2.6-mm/include/linux/inetdevice.h
@@ -99,6 +99,7 @@
 	unsigned char		ifa_flags;
 	unsigned char		ifa_prefixlen;
 	char			ifa_label[IFNAMSIZ];
+	struct net_namespace    *ifa_net_ns;
 };
 
 extern int register_inetaddr_notifier(struct notifier_block *nb);
Index: 2.6-mm/net/ipv4/devinet.c
===================================================================
--- 2.6-mm.orig/net/ipv4/devinet.c
+++ 2.6-mm/net/ipv4/devinet.c
@@ -54,6 +54,7 @@
 #include <linux/notifier.h>
 #include <linux/inetdevice.h>
 #include <linux/igmp.h>
+#include <linux/net_ns.h>
 #ifdef CONFIG_SYSCTL
 #include <linux/sysctl.h>
 #endif
@@ -257,6 +258,7 @@
 
 			if (!(ifa->ifa_flags & IFA_F_SECONDARY) ||
 			    ifa1->ifa_mask != ifa->ifa_mask ||
+			    ifa->ifa_net_ns != net_ns() ||
 			    !inet_ifa_match(ifa1->ifa_address, ifa)) {
 				ifap1 = &ifa->ifa_next;
 				prev_prom = ifa;
@@ -317,6 +319,8 @@
 	if (destroy) {
 		inet_free_ifa(ifa1);
 
+		put_net_ns(ifa1->ifa_net_ns);
+
 		if (!in_dev->ifa_list)
 			inetdev_destroy(in_dev);
 	}
@@ -343,6 +347,7 @@
 		    ifa->ifa_scope <= ifa1->ifa_scope)
 			last_primary = &ifa1->ifa_next;
 		if (ifa1->ifa_mask == ifa->ifa_mask &&
+		    ifa1->ifa_net_ns == ifa->ifa_net_ns &&
 		    inet_ifa_match(ifa1->ifa_address, ifa)) {
 			if (ifa1->ifa_local == ifa->ifa_local) {
 				inet_free_ifa(ifa);
@@ -437,6 +442,8 @@
 
 	for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
 	     ifap = &ifa->ifa_next) {
+		if (ifa->ifa_net_ns != net_ns())
+			continue;
 		if ((rta[IFA_LOCAL - 1] &&
 		     memcmp(RTA_DATA(rta[IFA_LOCAL - 1]),
 			    &ifa->ifa_local, 4)) ||
@@ -497,6 +504,9 @@
 	ifa->ifa_scope = ifm->ifa_scope;
 	in_dev_hold(in_dev);
 	ifa->ifa_dev   = in_dev;
+	ifa->ifa_net_ns = net_ns();
+	get_net_ns(net_ns());
+
 	if (rta[IFA_LABEL - 1])
 		rtattr_strlcpy(ifa->ifa_label, rta[IFA_LABEL - 1], IFNAMSIZ);
 	else
@@ -631,10 +641,15 @@
 			for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
 			     ifap = &ifa->ifa_next)
 				if (!strcmp(ifr.ifr_name, ifa->ifa_label))
-					break;
+					if (!ifa->ifa_net_ns ||
+					    ifa->ifa_net_ns == net_ns())
+						break;
 		}
 	}
 
+	if (ifa && ifa->ifa_net_ns && ifa->ifa_net_ns != net_ns())
+		goto done;
+
 	ret = -EADDRNOTAVAIL;
 	if (!ifa && cmd != SIOCSIFADDR && cmd != SIOCSIFFLAGS)
 		goto done;
@@ -678,6 +693,12 @@
 			ret = -ENOBUFS;
 			if ((ifa = inet_alloc_ifa()) == NULL)
 				break;
+			if (!LOOPBACK(sin->sin_addr.s_addr)) {
+				ifa->ifa_net_ns = net_ns();
+				get_net_ns(net_ns());
+			} else
+				ifa->ifa_net_ns = NULL;
+
 			if (colon)
 				memcpy(ifa->ifa_label, ifr.ifr_name, IFNAMSIZ);
 			else
@@ -782,6 +803,8 @@
 		goto out;
 
 	for (; ifa; ifa = ifa->ifa_next) {
+		if (ifa->ifa_net_ns && ifa->ifa_net_ns != net_ns())
+			continue;
 		if (!buf) {
 			done += sizeof(ifr);
 			continue;
@@ -1012,6 +1035,7 @@
 				  ifa->ifa_address = htonl(INADDR_LOOPBACK);
 				ifa->ifa_prefixlen = 8;
 				ifa->ifa_mask = inet_make_mask(8);
+				ifa->ifa_net_ns = NULL;
 				in_dev_hold(in_dev);
 				ifa->ifa_dev = in_dev;
 				ifa->ifa_scope = RT_SCOPE_HOST;
@@ -1110,6 +1134,8 @@
 
 		for (ifa = in_dev->ifa_list, ip_idx = 0; ifa;
 		     ifa = ifa->ifa_next, ip_idx++) {
+			if (ifa->ifa_net_ns && ifa->ifa_net_ns != net_ns())
+				continue;
 			if (ip_idx < s_ip_idx)
 				continue;
 			if (inet_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid,

--
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux