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

dlezcano
2006-06-09T21:08:29Z

[-- Attachment #1: inetdev_isolation.patch --]
[-- Type: text/plain, Size: 4457 bytes --]

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 <dlezcano@fr.ibm.com>
--
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,

--