Home » Mailing lists » Devel » [PATCH 00/16] core network namespace support
[PATCH 00/16] core network namespace support [message #19966] |
Sat, 08 September 2007 21:07 |
ebiederm
Messages: 1354 Registered: February 2006
|
Senior Member |
|
|
The following patchset was built against the latest net-2.6.24
tree, and should be safe to apply assume not issues are found during
the review. In the interest of keeping the patcheset to a reviewable
size, just the core of the network stack has been covered.
The 10,000 foot overview. We want to make it look to user space
like the kernel implements multiple network stacks.
To implement this some of the currently global variables in the
network stack need to have one instance per network namespace,
or the global data structure needs to have a network namespace
field.
Currently control enters the network stack in one of 4 major ways.
Through operations on a socket, through a packet coming in
from a network device, through miscellaneous syscalls from
a process, and through operations on a virtual filesystem.
So the current design calls for placing a pointer to
struct net (the network namespace structure) on network
devices, sockets, processes, and on filesystems so we
have a clear understanding of which network namespace
operations should be done in the context of.
Packets do not contain a pointer to a network device structure.
Instead their network device is derived from which network
device or which socket they are passing through.
On the input path we only need to look at the network namespace
to determine which routing tables to use, and which sockets the
packet can be destined for.
Similarly on the output path we only need to consult the network
namespace for the output routing tables which point to which
network devices we can use.
So while there are accesses to the network namespace as
we process each packet they are in well contained spots that occur
rarely.
Where the network namespace appears most is on the control,
setup, and clean up code paths, in the network stack that we
change rarely. There we currently don't have anything except
a global context so modifications are necessary, but since
the network parameter is not implicit it should not require
much thought to use.
The implementation strategy follows the classic global
lock reduction pattern. First all of the interfaces
at a given level in the network stack are made to filter
out traffic from anything except the initial network namespace,
and then those interfaces are allowed to see packets from
any network namespace. Then some subset of those interfaces
are taught to handle packets from all namespaces, after the
more specific protocol layers below them have been made to
filter those packets.
What this means is that we start out with large intrusive
stupid patches and end up with small patches that enable
small bits of functionality in the secondary network
namespaces.
Eric
_______________________________________________
Containers mailing list
Containers@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/containers
|
|
|
[PATCH 01/16] appletalk: In notifier handlers convert the void pointer to a netdevice [message #19967 is a reply to message #19966] |
Sat, 08 September 2007 21:09 |
ebiederm
Messages: 1354 Registered: February 2006
|
Senior Member |
|
|
This slightly improves code safetly and clarity.
Later network namespace patches touch this code so this is a
preliminary cleanup.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
net/appletalk/aarp.c | 7 ++++---
net/appletalk/ddp.c | 4 +++-
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c
index 3d1655f..80b5414 100644
--- a/net/appletalk/aarp.c
+++ b/net/appletalk/aarp.c
@@ -330,15 +330,16 @@ static void aarp_expire_timeout(unsigned long unused)
static int aarp_device_event(struct notifier_block *this, unsigned long event,
void *ptr)
{
+ struct net_device *dev = ptr;
int ct;
if (event == NETDEV_DOWN) {
write_lock_bh(&aarp_lock);
for (ct = 0; ct < AARP_HASH_SIZE; ct++) {
- __aarp_expire_device(&resolved[ct], ptr);
- __aarp_expire_device(&unresolved[ct], ptr);
- __aarp_expire_device(&proxies[ct], ptr);
+ __aarp_expire_device(&resolved[ct], dev);
+ __aarp_expire_device(&unresolved[ct], dev);
+ __aarp_expire_device(&proxies[ct], dev);
}
write_unlock_bh(&aarp_lock);
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index fbdfb12..594b597 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -647,9 +647,11 @@ static inline void atalk_dev_down(struct net_device *dev)
static int ddp_device_event(struct notifier_block *this, unsigned long event,
void *ptr)
{
+ struct net_device *dev = ptr;
+
if (event == NETDEV_DOWN)
/* Discard any use of this */
- atalk_dev_down(ptr);
+ atalk_dev_down(dev);
return NOTIFY_DONE;
}
--
1.5.3.rc6.17.g1911
_______________________________________________
Containers mailing list
Containers@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/containers
|
|
|
[PATCH 02/16] net: Don't implement dev_ifname32 inline [message #19968 is a reply to message #19967] |
Sat, 08 September 2007 21:13 |
ebiederm
Messages: 1354 Registered: February 2006
|
Senior Member |
|
|
The current implementation of dev_ifname makes maintenance difficult
because updates to the implementation of the ioctl have to made in two
places. So this patch updates dev_ifname32 to do a classic 32/64
structure conversion and call sys_ioctl like the rest of the
compat calls do.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
fs/compat_ioctl.c | 21 ++++++++++-----------
1 files changed, 10 insertions(+), 11 deletions(-)
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index a6c9078..361b994 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -324,22 +324,21 @@ struct ifconf32 {
static int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg)
{
- struct net_device *dev;
- struct ifreq32 ifr32;
+ struct ifreq __user *uifr;
int err;
- if (copy_from_user(&ifr32, compat_ptr(arg), sizeof(ifr32)))
+ uifr = compat_alloc_user_space(sizeof(struct ifreq));
+ if (copy_in_user(uifr, compat_ptr(arg), sizeof(struct ifreq32)));
return -EFAULT;
- dev = dev_get_by_index(ifr32.ifr_ifindex);
- if (!dev)
- return -ENODEV;
+ err = sys_ioctl(fd, SIOCGIFNAME, (unsigned long)uifr);
+ if (err)
+ return err;
- strlcpy(ifr32.ifr_name, dev->name, sizeof(ifr32.ifr_name));
- dev_put(dev);
-
- err = copy_to_user(compat_ptr(arg), &ifr32, sizeof(ifr32));
- return (err ? -EFAULT : 0);
+ if (copy_in_user(compat_ptr(arg), uifr, sizeof(struct ifreq32)))
+ return -EFAULT;
+
+ return 0;
}
static int dev_ifconf(unsigned int fd, unsigned int cmd, unsigned long arg)
--
1.5.3.rc6.17.g1911
_______________________________________________
Containers mailing list
Containers@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/containers
|
|
|
[PATCH 03/16] net: Basic network namespace infrastructure. [message #19969 is a reply to message #19968] |
Sat, 08 September 2007 21:15 |
ebiederm
Messages: 1354 Registered: February 2006
|
Senior Member |
|
|
This is the basic infrastructure needed to support network
namespaces. This infrastructure is:
- Registration functions to support initializing per network
namespace data when a network namespaces is created or destroyed.
- struct net. The network namespace data structure.
This structure will grow as variables are made per network
namespace but this is the minimal starting point.
- Functions to grab a reference to the network namespace.
I provide both get/put functions that keep a network namespace
from being freed. And hold/release functions serve as weak references
and will warn if their count is not zero when the data structure
is freed. Useful for dealing with more complicated data structures
like the ipv4 route cache.
- A list of all of the network namespaces so we can iterate over them.
- A slab for the network namespace data structure allowing leaks
to be spotted.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
include/net/net_namespace.h | 68 ++++++++++
net/core/Makefile | 2 +-
net/core/net_namespace.c | 292 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 361 insertions(+), 1 deletions(-)
create mode 100644 include/net/net_namespace.h
create mode 100644 net/core/net_namespace.c
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
new file mode 100644
index 0000000..6344b77
--- /dev/null
+++ b/include/net/net_namespace.h
@@ -0,0 +1,68 @@
+/*
+ * Operations on the network namespace
+ */
+#ifndef __NET_NET_NAMESPACE_H
+#define __NET_NET_NAMESPACE_H
+
+#include <asm/atomic.h>
+#include <linux/workqueue.h>
+#include <linux/list.h>
+
+struct net {
+ atomic_t count; /* To decided when the network
+ * namespace should be freed.
+ */
+ atomic_t use_count; /* To track references we
+ * destroy on demand
+ */
+ struct list_head list; /* list of network namespaces */
+ struct work_struct work; /* work struct for freeing */
+};
+
+extern struct net init_net;
+extern struct list_head net_namespace_list;
+
+extern void __put_net(struct net *net);
+
+static inline struct net *get_net(struct net *net)
+{
+ atomic_inc(&net->count);
+ return net;
+}
+
+static inline void put_net(struct net *net)
+{
+ if (atomic_dec_and_test(&net->count))
+ __put_net(net);
+}
+
+static inline struct net *hold_net(struct net *net)
+{
+ atomic_inc(&net->use_count);
+ return net;
+}
+
+static inline void release_net(struct net *net)
+{
+ atomic_dec(&net->use_count);
+}
+
+extern void net_lock(void);
+extern void net_unlock(void);
+
+#define for_each_net(VAR) \
+ list_for_each_entry(VAR, &net_namespace_list, list)
+
+
+struct pernet_operations {
+ struct list_head list;
+ int (*init)(struct net *net);
+ void (*exit)(struct net *net);
+};
+
+extern int register_pernet_subsys(struct pernet_operations *);
+extern void unregister_pernet_subsys(struct pernet_operations *);
+extern int register_pernet_device(struct pernet_operations *);
+extern void unregister_pernet_device(struct pernet_operations *);
+
+#endif /* __NET_NET_NAMESPACE_H */
diff --git a/net/core/Makefile b/net/core/Makefile
index 4751613..ea9b3f3 100644
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -3,7 +3,7 @@
#
obj-y := sock.o request_sock.o skbuff.o iovec.o datagram.o stream.o scm.o \
- gen_stats.o gen_estimator.o
+ gen_stats.o gen_estimator.o net_namespace.o
obj-$(CONFIG_SYSCTL) += sysctl_net_core.o
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
new file mode 100644
index 0000000..f259a9b
--- /dev/null
+++ b/net/core/net_namespace.c
@@ -0,0 +1,292 @@
+#include <linux/workqueue.h>
+#include <linux/rtnetlink.h>
+#include <linux/cache.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/delay.h>
+#include <net/net_namespace.h>
+
+/*
+ * Our network namespace constructor/destructor lists
+ */
+
+static LIST_HEAD(pernet_list);
+static struct list_head *first_device = &pernet_list;
+static DEFINE_MUTEX(net_mutex);
+
+static DEFINE_MUTEX(net_list_mutex);
+LIST_HEAD(net_namespace_list);
+
+static struct kmem_cache *net_cachep;
+
+struct net init_net;
+EXPORT_SYMBOL_GPL(init_net);
+
+void net_lock(void)
+{
+ mutex_lock(&net_list_mutex);
+}
+
+void net_unlock(void)
+{
+ mutex_unlock(&net_list_mutex);
+}
+
+static struct net *net_alloc(void)
+{
+ return kmem_cache_alloc(net_cachep, GFP_KERNEL);
+}
+
+static void net_free(struct net *net)
+{
+ if (!net)
+ return;
+
+ if (unlikely(atomic_read(&net->use_count) != 0)) {
+ printk(KERN_EMERG "network namespace not free! Usage: %d\n",
+ atomic_read(&net->use_count));
+ return;
+ }
+
+ kmem_cache_free(net_cachep, net);
+}
+
+static void cleanup_net(struct work_struct *work)
+{
+ struct pernet_operations *ops;
+ struct list_head *ptr;
+ struct net *net;
+
+ net = container_of(work, struct net, work);
+
+ mutex_lock(&net_mutex);
+
+ /* Don't let anyone else find us. */
+ net_lock();
+ list_del(&net->list);
+ net_unlock();
+
+ /* Run all of the network namespace exit methods */
+ list_for_each_prev(ptr, &pernet_list) {
+ ops = list_entry(ptr, struct pernet_operations, list);
+ if (ops->exit)
+ ops->exit(net);
+ }
+
+ mutex_unlock(&net_mutex);
+
+ /* Ensure there are no outstanding rcu callbacks using this
+ * network namespace.
+ */
+ rcu_barrier();
+
+ /* Finally it is safe to free my network namespace structure */
+ net_free(net);
+}
+
+
+void __put_net(struct net *net)
+{
+ /* Cleanup the network namespace in process context */
+ INIT_WORK(&net->work, cleanup_net);
+ schedule_work(&net->work);
+}
+EXPORT_SYMBOL_GPL(__put_net);
+
+/*
+ * setup_net runs the initializers for the network namespace object.
+ */
+static int setup_net(struct net *net)
+{
+ /* Must be called with net_mutex held */
+ struct pernet_operations *ops;
+ struct list_head *ptr;
+ int error;
+
+ memset(net, 0, sizeof(struct net));
+ atomic_set(&net->count, 1);
+ atomic_set(&net->use_count, 0);
+
+ error = 0;
+ list_for_each(ptr, &pernet_list) {
+ ops = list_entry(ptr, struct pernet_operations, list);
+ if (ops->init) {
+ error = ops->init(net);
+ if (error < 0)
+ goto out_undo;
+ }
+ }
+out:
+ return error;
+out_undo:
+ /* Walk through the list backwards calling the exit functions
+ * for the pernet modules whose init functions did not fail.
+ */
+ for (ptr = ptr->prev; ptr != &pernet_list; ptr = ptr->prev) {
+ ops = list_entry(ptr, struct pernet_operations, list);
+ if (ops->exit)
+ ops->exit(net);
+ }
+ goto out;
+}
+
+static int __init net_ns_init(void)
+{
+ int err;
+
+ printk(KERN_INFO "net_namespace: %zd bytes\n", sizeof(struct net));
+ net_cachep = kmem_cache_create("net_namespace", sizeof(struct net),
+ SMP_CACHE_BYTES,
+ SLAB_PANIC, NULL);
+ mutex_lock(&net_mutex);
+ err = setup_net(&init_net);
+
+ net_lock();
+ list_add_tail(&init_net.list, &net_namespace_list);
+ net_unlock();
+
+ mutex_unlock(&net_mutex);
+ if (err)
+ panic("Could not setup the initial network namespace");
+
+ return 0;
+}
+
+pure_initcall(net_ns_init);
+
+static int register_pernet_operations(struct list_head *list,
+ struct pernet_operations *ops)
+{
+ struct net *net, *undo_net;
+ int error;
+
+ error = 0;
+ list_add_tail(&ops->list, list);
+ for_each_net(net) {
+ if (ops->init) {
+ error = ops->init(net);
+ if (error)
+ goto out_undo;
+ }
+ }
+out:
+ return error;
+
+out_undo:
+ /* If I have an error cleanup all namespaces I initialized */
+ list_del(&ops->list);
+ for_each_net(undo_net) {
+ if (undo_net == net)
+ goto undone;
+ if (ops->exit)
+ ops->exit(undo_net);
+ }
+undone:
+ goto out;
+}
+
+static void unregister_pernet_operations(struct pernet_operations *ops)
+{
+ struct net *net;
+
+ list_del(&ops->list);
+ for_each_net(net)
+ if (ops->exit)
+ ops->exit(net);
+}
+
+/**
+ * register_pernet_subsys - register a network namespace subsystem
+ * @ops: pernet operations structure for the subsystem
+ *
+ * Register a subsystem which has init and exit functions
+ * that are called when network namespaces are created and
+ * destroyed respectively.
+ *
+ * When registered all network namespace init functions are
+ * called for every existing network namespace. Allowing kernel
+ * modules to have a race free view of the set of network namespaces.
+ *
+ * When a new network namespace is created all of the init
+ * methods are called in the order in which they were registered.
+ *
+ * When a network namespace is destroyed all of the exit methods
+ * are called in the reverse of the order with which they were
+ * registered.
+ */
+int register_pernet_subsys(struct pernet_operations *ops)
+{
+ int error;
+ mutex_lock(&net_mutex);
+ error = register_pernet_operations(first_device, ops);
+ mutex_unlock(&net_mutex);
+ return error;
+}
+EXPORT_SYMBOL_GPL(register_pernet_subsys);
+
+/**
+ * unregister_pernet_subsys - unregister a network namespace subsystem
+ * @ops: pernet operations structure to manipulate
+ *
+ * Remove the pernet operations structure from the list to be
+ * used when network namespaces are created or destoryed. In
+ * addition run the exit method for all existing network
+ * namespaces.
+ */
+void unregister_pernet_subsys(struct pernet_operations *module)
+{
+ mutex_lock(&net_mutex);
+ unregister_pernet_operations(module);
+ mutex_unlock(&net_mutex);
+}
+EXPORT_SYMBOL_GPL(unregister_pernet_subsys);
+
+/**
+ * register_pernet_device - register a network namespace device
+ * @ops: pernet operations structure for the subsystem
+ *
+ * Register a device which has init and exit functions
+ * that are called when network namespaces are created and
+ * destroyed respectively.
+ *
+ * When registered all network namespa
...
|
|
|
[PATCH 04/16] net: Add a network namespace parameter to tasks [message #19970 is a reply to message #19969] |
Sat, 08 September 2007 21:17 |
ebiederm
Messages: 1354 Registered: February 2006
|
Senior Member |
|
|
This is the network namespace from which all which all sockets
and anything else under user control ultimately get their network
namespace parameters.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
include/linux/init_task.h | 2 ++
include/linux/nsproxy.h | 1 +
2 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index cab741c..685d631 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -9,6 +9,7 @@
#include <linux/ipc.h>
#include <linux/pid_namespace.h>
#include <linux/user_namespace.h>
+#include <net/net_namespace.h>
#define INIT_FDTABLE \
{ \
@@ -78,6 +79,7 @@ extern struct nsproxy init_nsproxy;
.nslock = __SPIN_LOCK_UNLOCKED(nsproxy.nslock), \
.uts_ns = &init_uts_ns, \
.mnt_ns = NULL, \
+ .net_ns = &init_net, \
INIT_IPC_NS(ipc_ns) \
.user_ns = &init_user_ns, \
}
diff --git a/include/linux/nsproxy.h b/include/linux/nsproxy.h
index ce06188..bec4485 100644
--- a/include/linux/nsproxy.h
+++ b/include/linux/nsproxy.h
@@ -29,6 +29,7 @@ struct nsproxy {
struct mnt_namespace *mnt_ns;
struct pid_namespace *pid_ns;
struct user_namespace *user_ns;
+ struct net *net_ns;
};
extern struct nsproxy init_nsproxy;
--
1.5.3.rc6.17.g1911
_______________________________________________
Containers mailing list
Containers@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/containers
|
|
|
|
[PATCH 07/16] net: Make /proc/net per network namespace [message #19972 is a reply to message #19971] |
Sat, 08 September 2007 21:20 |
ebiederm
Messages: 1354 Registered: February 2006
|
Senior Member |
|
|
This patch makes /proc/net per network namespace. It modifies the global
variables proc_net and proc_net_stat to be per network namespace.
The proc_net file helpers are modified to take a network namespace argument,
and all of their callers are fixed to pass &init_net for that argument.
This ensures that all of the /proc/net files are only visible and
usable in the initial network namespace until the code behind them
has been updated to be handle multiple network namespaces.
Making /proc/net per namespace is necessary as at least some files
in /proc/net depend upon the set of network devices which is per
network namespace, and even more files in /proc/net have contents
that are relevant to a single network namespace.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
drivers/isdn/divert/divert_procfs.c | 7 +-
drivers/isdn/hardware/eicon/diva_didd.c | 5 +-
drivers/isdn/hysdn/hysdn_procconf.c | 5 +-
drivers/net/bonding/bond_main.c | 7 +-
drivers/net/hamradio/bpqether.c | 5 +-
drivers/net/hamradio/scc.c | 5 +-
drivers/net/hamradio/yam.c | 5 +-
drivers/net/ibmveth.c | 7 +-
drivers/net/pppoe.c | 5 +-
drivers/net/pppol2tp.c | 5 +-
drivers/net/tokenring/lanstreamer.c | 5 +-
drivers/net/tokenring/olympic.c | 9 +-
drivers/net/wireless/hostap/hostap_main.c | 7 +-
drivers/net/wireless/strip.c | 5 +-
fs/proc/Makefile | 1 +
fs/proc/internal.h | 5 +
fs/proc/proc_net.c | 192 ++++++++++++++++++++
fs/proc/root.c | 8 +-
include/linux/proc_fs.h | 44 ++---
include/net/net_namespace.h | 5 +
net/802/tr.c | 3 +-
net/8021q/vlanproc.c | 5 +-
net/appletalk/atalk_proc.c | 7 +-
net/atm/proc.c | 5 +-
net/ax25/af_ax25.c | 13 +-
net/core/dev.c | 19 +-
net/core/dev_mcast.c | 3 +-
net/core/neighbour.c | 3 +-
net/core/pktgen.c | 9 +-
net/core/sock.c | 3 +-
net/dccp/probe.c | 7 +-
net/decnet/af_decnet.c | 5 +-
net/decnet/dn_dev.c | 5 +-
net/decnet/dn_neigh.c | 5 +-
net/decnet/dn_route.c | 5 +-
net/ieee80211/ieee80211_module.c | 7 +-
net/ipv4/arp.c | 3 +-
net/ipv4/fib_hash.c | 5 +-
net/ipv4/fib_trie.c | 17 +-
net/ipv4/igmp.c | 5 +-
net/ipv4/ipconfig.c | 3 +-
net/ipv4/ipmr.c | 5 +-
net/ipv4/ipvs/ip_vs_app.c | 5 +-
net/ipv4/ipvs/ip_vs_conn.c | 5 +-
net/ipv4/ipvs/ip_vs_ctl.c | 9 +-
net/ipv4/ipvs/ip_vs_lblcr.c | 5 +-
net/ipv4/netfilter/ip_queue.c | 8 +-
net/ipv4/netfilter/ipt_CLUSTERIP.c | 3 +-
net/ipv4/netfilter/ipt_recent.c | 5 +-
.../netfilter/nf_conntrack_l3proto_ipv4_compat.c | 17 +-
net/ipv4/proc.c | 11 +-
net/ipv4/raw.c | 5 +-
net/ipv4/route.c | 7 +-
net/ipv4/tcp_ipv4.c | 5 +-
net/ipv4/tcp_probe.c | 7 +-
net/ipv4/udp.c | 5 +-
net/ipv6/addrconf.c | 7 +-
net/ipv6/anycast.c | 5 +-
net/ipv6/ip6_flowlabel.c | 5 +-
net/ipv6/mcast.c | 9 +-
net/ipv6/netfilter/ip6_queue.c | 7 +-
net/ipv6/proc.c | 17 +-
net/ipv6/raw.c | 5 +-
net/ipv6/route.c | 9 +-
net/ipx/ipx_proc.c | 7 +-
net/irda/irproc.c | 5 +-
net/key/af_key.c | 5 +-
net/llc/llc_proc.c | 7 +-
net/netfilter/core.c | 3 +-
net/netfilter/nf_conntrack_expect.c | 5 +-
net/netfilter/nf_conntrack_standalone.c | 13 +-
net/netfilter/x_tables.c | 17 +-
net/netfilter/xt_hashlimit.c | 11 +-
net/netlink/af_netlink.c | 3 +-
net/netrom/af_netrom.c | 13 +-
net/packet/af_packet.c | 5 +-
net/rose/af_rose.c | 17 +-
net/rxrpc/af_rxrpc.c | 9 +-
net/sched/sch_api.c | 3 +-
net/sctp/protocol.c | 5 +-
net/sunrpc/stats.c | 5 +-
net/unix/af_unix.c | 5 +-
net/wanrouter/wanproc.c | 7 +-
net/wireless/wext.c | 3 +-
net/x25/x25_proc.c | 7 +-
85 files changed, 534 insertions(+), 261 deletions(-)
create mode 100644 fs/proc/proc_net.c
diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c
index 559a0d0..4fd4c46 100644
--- a/drivers/isdn/divert/divert_procfs.c
+++ b/drivers/isdn/divert/divert_procfs.c
@@ -17,6 +17,7 @@
#include <linux/fs.h>
#endif
#include <linux/isdnif.h>
+#include <net/net_namespace.h>
#include "isdn_divert.h"
@@ -284,12 +285,12 @@ divert_dev_init(void)
init_waitqueue_head(&rd_queue);
#ifdef CONFIG_PROC_FS
- isdn_proc_entry = proc_mkdir("net/isdn", NULL);
+ isdn_proc_entry = proc_mkdir("isdn", init_net.proc_net);
if (!isdn_proc_entry)
return (-1);
isdn_divert_entry = create_proc_entry("divert", S_IFREG | S_IRUGO, isdn_proc_entry);
if (!isdn_divert_entry) {
- remove_proc_entry("net/isdn", NULL);
+ remove_proc_entry("isdn", init_net.proc_net);
return (-1);
}
isdn_divert_entry->proc_fops = &isdn_fops;
@@ -309,7 +310,7 @@ divert_dev_deinit(void)
#ifdef CONFIG_PROC_FS
remove_proc_entry("divert", isdn_proc_entry);
- remove_proc_entry("net/isdn", NULL);
+ remove_proc_entry("isdn", init_net.proc_net);
#endif /* CONFIG_PROC_FS */
return (0);
diff --git a/drivers/isdn/hardware/eicon/diva_didd.c b/drivers/isdn/hardware/eicon/diva_didd.c
index d755d90..993b14c 100644
--- a/drivers/isdn/hardware/eicon/diva_didd.c
+++ b/drivers/isdn/hardware/eicon/diva_didd.c
@@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
+#include <net/net_namespace.h>
#include "platform.h"
#include "di_defs.h"
@@ -86,7 +87,7 @@ proc_read(char *page, char **start, off_t off, int count, int *eof,
static int DIVA_INIT_FUNCTION create_proc(void)
{
- proc_net_eicon = proc_mkdir("net/eicon", NULL);
+ proc_net_eicon = proc_mkdir("eicon", init_net.proc_net);
if (proc_net_eicon) {
if ((proc_didd =
@@ -102,7 +103,7 @@ static int DIVA_INIT_FUNCTION create_proc(void)
static void remove_proc(void)
{
remove_proc_entry(DRIVERLNAME, proc_net_eicon);
- remove_proc_entry("net/eicon", NULL);
+ remove_proc_entry("eicon", init_net.proc_net);
}
static int DIVA_INIT_FUNCTION divadidd_init(void)
diff --git a/drivers/isdn/hysdn/hysdn_procconf.c b/drivers/isdn/hysdn/hysdn_procconf.c
index dc477e0..27d890b 100644
--- a/drivers/isdn/hysdn/hysdn_procconf.c
+++ b/drivers/isdn/hysdn/hysdn_procconf.c
@@ -16,6 +16,7 @@
#include <linux/proc_fs.h>
#include <linux/pci.h>
#include <linux/smp_lock.h>
+#include <net/net_namespace.h>
#include "hysdn_defs.h"
@@ -392,7 +393,7 @@ hysdn_procconf_init(void)
hysdn_card *card;
unsigned char conf_name[20];
- hysdn_proc_entry = proc_mkdir(PROC_SUBDIR_NAME, proc_net);
+ hysdn_proc_entry = proc_mkdir(PROC_SUBDIR_NAME, init_net.proc_net);
if (!hysdn_proc_entry) {
printk(KERN_ERR "HYSDN: unable to create hysdn subdir\n");
return (-1);
@@ -437,5 +438,5 @@ hysdn_procconf_release(void)
card = card->next; /* point to next card */
}
- remove_proc_entry(PROC_SUBDIR_NAME, proc_net);
+ remove_proc_entry(PROC_SUBDIR_NAME, init_net.proc_net);
}
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 1afda32..5de648f 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -75,6 +75,7 @@
#include <linux/if_vlan.h>
#include <linux/if_bonding.h>
#include <net/route.h>
+#include <net/net_namespace.h>
#include "bonding.h"
#include "bond_3ad.h"
#include "bond_alb.h"
@@ -3144,7 +3145,7 @@ static void bond_create_proc_dir(void)
{
int len = strlen(DRV_NAME);
- for (bond_proc_dir = proc_net->subdir; bond_proc_dir;
+ for (bond_proc_dir = init_net.proc_net->subdir; bond_proc_dir;
bond_proc_dir = bond_proc_dir->next) {
if ((bond_proc_dir->namelen == len) &&
!memcmp(bond_proc_dir->name, DRV_NAME, len)) {
@@ -3153,7 +3154,7 @@ static void bond_create_proc_dir(void)
}
if (!bond_proc_dir) {
- bond_proc_dir = proc_mkdir(DRV_NAME, proc_net);
+ bond_proc_dir = proc_mkdir(DRV_NAME, init_net.proc_net);
if (bond_proc_dir) {
bond_proc_dir->owner = THIS_MODULE;
} else {
@@ -3188,7 +3189,7 @@ static void bond_destroy_proc_dir(void)
bond_proc_dir->owner = NULL;
}
} else {
- remove_proc_entry(DRV_NAME, proc_net);
+ remove_proc_entry(DRV_NAME, init_net.proc_net);
bond_proc_dir = NULL;
}
}
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index cc0ee93..1699d42 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -83,6 +83,7 @@
#include <net/ip.h>
#include <net/arp.h>
+#include <net/net_namespace.h>
#include <linux/bpqether.h>
@@ -594,7 +595,7 @@ static int bpq_device_event(struct notifier_block *this,unsigned long event, voi
static int __init bpq_init_driver(void)
{
#ifdef CONFIG_PROC_FS
- if (!proc_net_fops_create("bpqether", S_IRUGO, &bpq_info_fops)) {
+ if (!proc_net_fops_create(&init_net, "bpqether", S_IRUGO, &bpq_info_fops)) {
printk(KERN_ERR
"bpq: cannot create /proc/net/bpqether entry.\n");
return -ENOENT;
@@ -618,7 +619,7 @@ static void __exit bpq_cleanup_driver(void)
unregister_netdevice_notifier(&bpq_dev_notifier);
- proc_net_remove("bpqether");
+ proc_net_remove(&init_net, "bpqether");
rtnl_lock();
while (!list_empty(&bpq_devices)) {
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
index 6fdaad5..39b3b82 100644
--- a/drivers/net/hamradio/scc.c
+++ b/drivers/net/hamradio/scc.c
@@ -174,6 +174,7 @@
#include <linux/seq_file.h>
#include <linux/bitops.h>
+#include <net/net_namespace.h>
#include <net/ax25.h>
#include <asm/irq.h>
@@ -2114,7 +2115,7 @@ static int __init scc_init_driver (void)
}
rtnl_unlock();
- proc_net_fops_create("z8530drv", 0, &scc_net_seq_fops);
+ proc_net_fops_create(&init_net, "z8530drv", 0, &scc_net_seq_fops);
return 0;
}
@@ -2169,7 +2170,7 @@ static void __exit scc_cleanup_driver(void)
if (Vector_Latch)
release_region(Vector_Latch, 1);
- proc_net_remove("z8530drv");
+ proc_net_remove(&init_net, "z8530drv");
}
MODULE_AUTHOR("Joerg Reuter <jreuter@yaina.de>");
diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c
index 467559d..401724d 100644
--- a/drivers/net/hamradio/yam.c
+++ b/drivers/net/hamradio/yam.c
@@ -65,6 +65,7 @@
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <net/net_namespace.h>
#include <asm/uaccess.h>
#include <linux/init.h>
@@ -1142,7 +1143,7 @@ static int __init yam_init_driver(void)
yam_timer.expires = jiffies + HZ / 100;
add_timer(&yam_timer);
- proc_net_fops_create("yam", S_IRUGO, &yam_info_fops);
+ proc_net_fops_create(&init_net, "yam", S_IRUGO, &yam_info_fops);
return 0;
error:
while (--i >= 0) {
@@ -1174,7 +1175,7 @@ static void __exit yam_cleanup_driver(void)
kfree(p);
}
- proc_net_remove("yam");
+ proc_net_remove(&init_net, "yam");
}
/* --------------------------------------------------------------------- */
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index 996aaca..74ca22d 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -47,6 +47,7 @@
#include <linux/mm.h>
#include <linux/ethtool.h>
#include <linux/proc_fs.h>
+#include <net/net_namespace.h>
#include <asm/semaphore.h>
#include <asm/hvcall.h>
#include <asm/atomic.h>
@@ -97,7 +98,7 @@ static void ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter);
static struct kobj_type ktype_veth_pool;
#ifdef CONFIG_PROC_FS
-#define IBMVETH_PROC_DIR "net/ibmveth"
+#define IBMVETH_PROC_DIR "ibmveth"
static struct proc_dir_entry *ibmveth_proc_dir;
#endif
@@ -1091,7 +1092,7 @@ static int __devexit ibmveth_remove(struct vio_dev *dev)
#ifdef CONFIG_PROC_FS
static void ibmveth_proc_register_driver(void)
{
- ibmveth_proc_dir = proc_mkdir(IBMVETH_PROC_DIR, NULL);
+ ibmveth_proc_dir = proc_mkdir(IBMVETH_PROC_DIR, init_net.proc_net);
if (ibmveth_proc_dir) {
SET_MODULE_OWNER(ibmveth_proc_dir);
}
@@ -1099,7 +1100,7 @@ static void ibmveth_proc_register_driver(void)
static void ibmveth_proc_unregister_driver(void)
{
- remove_proc_entry(IBMVETH_PROC_DIR, NULL);
+ remove_proc_entry(IBMVETH_PROC_DIR, init_net.proc_net);
}
static void *ibmveth_seq_start(struct seq_file *seq, loff_t *pos)
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index 68631a5..a9b6971 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -78,6 +78,7 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <net/net_namespace.h>
#include <net/sock.h>
#include <asm/uaccess.h>
@@ -1069,7 +1070,7 @@ static int __init pppoe_proc_init(void)
{
struct proc_dir_entry *p;
- p = create_proc_entry("net/pppoe", S_IRUGO, NULL);
+ p = create_proc_entry("pppoe", S_IRUGO, init_net.proc_net);
if (!p)
return -ENOMEM;
@@ -1140,7 +1141,7 @@ static void __exit pppoe_exit(void)
dev_remove_pack(&pppoes_ptype);
dev_remove_pack(&pppoed_ptype);
unregister_netdevice_notifier(&pppoe_notifier);
- remove_proc_entry("net/pppoe", NULL);
+ remove_proc_entry("pppoe", init_net.proc_net);
proto_unregister(&pppoe_sk_proto);
}
diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c
index 266e8b3..c12e0a8 100644
--- a/drivers/net/pppol2tp.c
+++ b/drivers/net/pppol2tp.c
@@ -91,6 +91,7 @@
#include <linux/hash.h>
#include <linux/sort.h>
#include <linux/proc_fs.h>
+#include <net/net_namespace.h>
#include <net/dst.h>
#include <net/ip.h>
#include <net/udp.h>
@@ -2456,7 +2457,7 @@ static int __init pppol2tp_init(void)
goto out_unregister_pppol2tp_proto;
#ifdef CONFIG_PROC_FS
- pppol2tp_proc = create_proc_entry("pppol2tp", 0, proc_net);
+ pppol2tp_proc = create_proc_entry("pppol2tp", 0, init_net.proc_net);
if (!pppol2tp_proc) {
err = -ENOMEM;
goto out_unregister_pppox_proto;
@@ -2481,7 +2482,7 @@ static void __exit pppol2tp_exit(void)
unregister_pppox_proto(PX_PROTO_OL2TP);
#ifdef CONFIG_PROC_FS
- remove_proc_entry("pppol2tp", proc_net);
+ remove_proc_entry("pppol2tp", init_net.proc_net);
#endif
proto_unregister(&pppol2tp_sk_proto);
}
diff --git a/drivers/net/tokenring/lanstreamer.c b/drivers/net/tokenring/lanstreamer.c
index 5d849c0..fc44955 100644
--- a/drivers/net/tokenring/lanstreamer.c
+++ b/drivers/net/tokenring/lanstreamer.c
@@ -123,6 +123,7 @@
#include <linux/bitops.h>
#include <linux/jiffies.h>
+#include <net/net_namespace.h>
#include <net/checksum.h>
#include <asm/io.h>
@@ -250,7 +251,7 @@ static int __devinit streamer_init_one(struct pci_dev *pdev,
#if STREAMER_NETWORK_MONITOR
#ifdef CONFIG_PROC_FS
if (!dev_streamer)
- create_proc_read_entry("net/streamer_tr", 0, 0,
+ create_proc_read_entry("streamer_tr", 0, init_net.proc_net,
streamer_proc_info, NULL);
streamer_priv->next = dev_streamer;
dev_streamer = streamer_priv;
@@ -423,7 +424,7 @@ static void __devexit streamer_remove_one(struct pci_dev *pdev)
}
}
if (!dev_streamer)
- remove_proc_entry("net/streamer_tr", NULL);
+ remove_proc_entry("streamer_tr", init_net.proc_net);
}
#endif
#endif
diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c
index 09b3cfb..c323101 100644
--- a/drivers/net/tokenring/olympic.c
+++ b/drivers/net/tokenring/olympic.c
@@ -102,6 +102,7 @@
#include <linux/jiffies.h>
#include <net/checksum.h>
+#include <net/net_namespace.h>
#include <asm/io.h>
#include <asm/system.h>
@@ -268,9 +269,9 @@ static int __devinit olympic_probe(struct pci_dev *pdev, const struct pci_device
printk("Olympic: %s registered as: %s\n",olympic_priv->olympic_card_name,dev->name);
if (olympic_priv->olympic_network_monitor) { /* Must go after register_netdev as we need the device name */
char proc_name[20] ;
- strcpy(proc_name,"net/olympic_") ;
+ strcpy(proc_name,"olympic_") ;
strcat(proc_name,dev->name) ;
- create_proc_read_entry(proc_name,0,NULL,olympic_proc_info,(void *)dev) ;
+ create_proc_read_entry(proc_name,0,init_net.proc_net,olympic_proc_info,(void *)dev) ;
printk("Olympic: Network Monitor information: /proc/%s\n",proc_name);
}
return 0 ;
@@ -1752,9 +1753,9 @@ static void __devexit olympic_remove_one(struct pci_dev *pdev)
if (olympic_priv->olympic_network_monitor) {
char proc_name[20] ;
- strcpy(proc_name,"net/olympic_") ;
+ strcpy(proc_name,"olympic_") ;
strcat(proc_name,dev->name) ;
- remove_proc_entry(proc_name,NULL);
+ remove_proc_entry(proc_name,init_net.proc_net);
}
unregister_netdev(dev) ;
iounmap(olympic_priv->olympic_mmio) ;
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c
index 446de51..9a470e8 100644
--- a/drivers/net/wireless/hostap/hostap_main.c
+++ b/drivers/net/wireless/hostap/hostap_main.c
@@ -24,6 +24,7 @@
#include <linux/rtnetlink.h>
#include <linux/wireless.h>
#include <linux/etherdevice.h>
+#include <net/net_namespace.h>
#include <net/iw_handler.h>
#include <net/ieee80211.h>
#include <net/ieee80211_crypt.h>
@@ -1093,8 +1094,8 @@ struct proc_dir_entry *hostap_proc;
static int __init hostap_init(void)
{
- if (proc_net != NULL) {
- hostap_proc = proc_mkdir("hostap", proc_net);
+ if (init_net.proc_net != NULL) {
+ hostap_proc = proc_mkdir("hostap", init_net.proc_net);
if (!hostap_proc)
printk(KERN_WARNING "Failed to mkdir "
"/proc/net/hostap\n");
@@ -1109,7 +1110,7 @@ static void __exit hostap_exit(void)
{
if (hostap_proc != NULL) {
hostap_proc = NULL;
- remove_proc_entry("hostap", proc_net);
+ remove_proc_entry("hostap", init_net.proc_net);
}
}
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
index ef32a5c..edb214e 100644
--- a/drivers/net/wireless/strip.c
+++ b/drivers/net/wireless/strip.c
@@ -107,6 +107,7 @@ static const char StripVersion[] = "1.3A-STUART.CHESHIRE";
#include <linux/serialP.h>
#include <linux/rcupdate.h>
#include <net/arp.h>
+#include <net/net_namespace.h>
#include <linux/ip.h>
#include <linux/tcp.h>
@@ -2787,7 +2788,7 @@ static int __init strip_init_driver(void)
/*
* Register the status file with /proc
*/
- proc_net_fops_create("strip", S_IFREG | S_IRUGO, &strip_seq_fops);
+ proc_net_fops_create(&init_net, "strip", S_IFREG | S_IRUGO, &strip_seq_fops);
return status;
}
@@ -2809,7 +2810,7 @@ static void __exit strip_exit_driver(void)
}
/* Unregister with the /proc/net file here. */
- proc_net_remove("strip");
+ proc_net_remove(&init_net, "strip");
if ((i = tty_unregister_ldisc(N_STRIP)))
printk(KERN_ERR "STRIP: can't unregister line discipline (err = %d)\n", i);
diff --git a/fs/proc/Makefile b/fs/proc/Makefile
index bce38e3..ebaba02 100644
--- a/fs/proc/Makefile
+++ b/fs/proc/Makefile
@@ -11,6 +11,7 @@ proc-y += inode.o root.o base.o generic.o array.o \
proc_tty.o proc_misc.o
proc-$(CONFIG_PROC_SYSCTL) += proc_sysctl.o
+proc-$(CONFIG_NET) += proc_net.o
proc-$(CONFIG_PROC_KCORE) += kcore.o
proc-$(CONFIG_PROC_VMCORE) += vmcore.o
proc-$(CONFIG_PROC_DEVICETREE) += proc_devtree.o
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index b215c35..1820eb2 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -16,6 +16,11 @@ extern int proc_sys_init(void);
#else
static inline void proc_sys_init(void) { }
#endif
+#ifdef CONFIG_NET
+extern int proc_net_init(void);
+#else
+static inline int proc_net_init(void) { return 0; }
+#endif
struct vmalloc_info {
unsigned long used;
diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c
new file mode 100644
index 0000000..45dde2f
--- /dev/null
+++ b/fs/proc/proc_net.c
@@ -0,0 +1,192 @@
+/*
+ * linux/fs/proc/net.c
+ *
+ * Copyright (C) 2007
+ *
+ * Author: Eric Biederman <ebiederm@xmission.com>
+ *
+ * proc net directory handling functions
+ */
+
+#include <asm/uaccess.h>
+
+#include <linux/errno.h>
+#include <linux/time.h>
+#include <linux/proc_fs.h>
+#include <linux/stat.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/bitops.h>
+#include <linux/smp_lock.h>
+#include <linux/mount.h>
+#include <linux/nsproxy.h>
+#include <net/net_namespace.h>
+
+#include "internal.h"
+
+
+struct proc_dir_entry *proc_net_create(struct net *net,
+ const char *name, mode_t mode, get_info_t *get_info)
+{
+ return create_proc_info_entry(name,mode, net->proc_net, get_info);
+}
+
+struct proc_dir_entry *proc_net_fops_create(struct net *net,
+ const char *name, mode_t mode, const struct file_operations *fops)
+{
+ struct proc_dir_entry *res;
+
+ res = create_proc_entry(name, mode, net->proc_net);
+ if (res)
+ res->proc_fops = fops;
+ return res;
+}
+
+void proc_net_remove(struct net *net, const char *name)
+{
+ remove_proc_entry(name, net->proc_net);
+}
+
+
+static struct proc_dir_entry *proc_net_shadow;
+
+static struct dentry *proc_net_shadow_dentry(struct dentry *parent,
+ struct proc_dir_entry *de)
+{
+ struct dentry *shadow = NULL;
+ struct inode *inode;
+ if (!de)
+ goto out;
+ de_get(de);
+ inode = proc_get_inode(parent->d_inode->i_sb, de->low_ino, de);
+ if (!inode)
+ goto out_de_put;
+ shadow = d_alloc_name(parent, de->name);
+ if (!shadow)
+ goto out_iput;
+ shadow->d_op = parent->d_op; /* proc_dentry_operations */
+ d_instantiate(shadow, inode);
+out:
+ return shadow;
+out_iput:
+ iput(inode);
+out_de_put:
+ de_put(de);
+ goto out;
+}
+
+static void *proc_net_follow_link(struct dentry *parent, struct nameidata *nd)
+{
+ struct net *net = current->nsproxy->net_ns;
+ struct dentry *shadow;
+ shadow = proc_net_shadow_dentry(parent, net->proc_net);
+ if (!shadow)
+ return ERR_PTR(-ENOENT);
+
+ dput(nd->dentry);
+ /* My dentry count is 1 and that should be enough as the
+ * shadow dentry is thrown away immediately.
+ */
+ nd->dentry = shadow;
+ return NULL;
+}
+
+static struct dentry *proc_net_lookup(struct inode *dir, struct dentry *dentry,
+ struct nameidata *nd)
+{
+ struct net *net = current->nsproxy->net_ns;
+ struct dentry *shadow;
+
+ shadow = proc_net_shadow_dentry(nd->dentry, net->proc_net);
+ if (!shadow)
+ return ERR_PTR(-ENOENT);
+
+ dput(nd->dentry);
+ nd->dentry = shadow;
+
+ return shadow->d_inode->i_op->lookup(shadow->d_inode, dentry, nd);
+}
+
+static int proc_net_setattr(struct dentry *dentry, struct iattr *iattr)
+{
+ struct net *net = current->nsproxy->net_ns;
+ struct dentry *shadow;
+ int ret;
+
+ shadow = proc_net_shadow_dentry(dentry->d_parent, net->proc_net);
+ if (!shadow)
+ return -ENOENT;
+ ret = shadow->d_inode->i_op->setattr(shadow, iattr);
+ dput(shadow);
+ return ret;
+}
+
+static const struct file_operations proc_net_dir_operations = {
+ .read = generic_read_dir,
+};
+
+static struct inode_operations proc_net_dir_inode_operations = {
+ .follow_link = proc_net_follow_link,
+ .lookup = proc_net_lookup,
+ .setattr = proc_net_setattr,
+};
+
+static int proc_net_ns_init(struct net *net)
+{
+ struct proc_dir_entry *root, *netd, *net_statd;
+ int err;
+
+ err = -ENOMEM;
+ root = kzalloc(sizeof(*root), GFP_KERNEL);
+ if (!root)
+ goto out;
+
+ err = -EEXIST;
+ netd = proc_mkdir("net", root);
+ if (!netd)
+ goto free_root;
+
+ err = -EEXIST;
+ net_statd = proc_mkdir("stat", netd);
+ if (!net_statd)
+ goto free_net;
+
+ root->data = net;
+ netd->data = net;
+ net_statd->data = net;
+
+ net->proc_net_root = root;
+ net->proc_net = netd;
+ net->proc_net_stat = net_statd;
+ err = 0;
+
+out:
+ return err;
+free_net:
+ remove_proc_entry("net", root);
+free_root:
+ kfree(root);
+ goto out;
+}
+
+static void proc_net_ns_exit(struct net *net)
+{
+ remove_proc_entry("stat", net->proc_net);
+ remove_proc_entry("net", net->proc_net_root);
+ kfree(net->proc_net_root);
+}
+
+struct pernet_operations proc_net_ns_ops = {
+ .init = proc_net_ns_init,
+ .exit = proc_net_ns_exit,
+};
+
+int proc_net_init(void)
+{
+ proc_net_shadow = proc_mkdir("net", NULL);
+ proc_net_shadow->proc_iops = &proc_net_dir_inode_operations;
+ proc_net_shadow->proc_fops = &proc_net_dir_operations;
+
+ return register_pernet_subsys(&proc_net_ns_ops);
+}
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 41f1703..cf30466 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -21,7 +21,7 @@
#include "internal.h"
-struct proc_dir_entry *proc_net, *proc_net_stat, *proc_bus, *proc_root_fs, *proc_root_driver;
+struct proc_dir_entry *proc_bus, *proc_root_fs, *proc_root_driver;
static int proc_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data, struct vfsmount *mnt)
@@ -61,8 +61,8 @@ void __init proc_root_init(void)
return;
}
proc_misc_init();
- proc_net = proc_mkdir("net", NULL);
- proc_net_stat = proc_mkdir("net/stat", NULL);
+
+ proc_net_init();
#ifdef CONFIG_SYSVIPC
proc_mkdir("sysvipc", NULL);
@@ -159,7 +159,5 @@ EXPORT_SYMBOL(create_proc_entry);
EXPORT_SYMBOL(remove_proc_entry);
EXPORT_SYMBOL(proc_root);
EXPORT_SYMBOL(proc_root_fs);
-EXPORT_SYMBOL(proc_net);
-EXPORT_SYMBOL(proc_net_stat);
EXPORT_SYMBOL(proc_bus);
EXPORT_SYMBOL(proc_root_driver);
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index cd13a78..5964670 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -7,6 +7,7 @@
#include <linux/magic.h>
#include <asm/atomic.h>
+struct net;
struct completion;
/*
@@ -97,8 +98,6 @@ struct vmcore {
extern struct proc_dir_entry proc_root;
extern struct proc_dir_entry *proc_root_fs;
-extern struct proc_dir_entry *proc_net;
-extern struct proc_dir_entry *proc_net_stat;
extern struct proc_dir_entry *proc_bus;
extern struct proc_dir_entry *proc_root_driver;
extern struct proc_dir_entry *proc_root_kcore;
@@ -192,36 +191,21 @@ static inline struct proc_dir_entry *create_proc_info_entry(const char *name,
if (res) res->get_info=get_info;
return res;
}
-
-static inline struct proc_dir_entry *proc_net_create(const char *name,
- mode_t mode, get_info_t *get_info)
-{
- return create_proc_info_entry(name,mode,proc_net,get_info);
-}
-static inline struct proc_dir_entry *proc_net_fops_create(const char *name,
- mode_t mode, const struct file_operations *fops)
-{
- struct proc_dir_entry *res = create_proc_entry(name, mode, proc_net);
- if (res)
- res->proc_fops = fops;
- return res;
-}
-
-static inline void proc_net_remove(const char *name)
-{
- remove_proc_entry(name,proc_net);
-}
+extern struct proc_dir_entry *proc_net_create(struct net *net,
+ const char *name, mode_t mode, get_info_t *get_info);
+extern struct proc_dir_entry *proc_net_fops_create(struct net *net,
+ const char *name, mode_t mode, const struct file_operations *fops);
+extern void proc_net_remove(struct net *net, const char *name);
#else
#define proc_root_driver NULL
-#define proc_net NULL
#define proc_bus NULL
-#define proc_net_fops_create(name, mode, fops) ({ (void)(mode), NULL; })
-#define proc_net_create(name, mode, info) ({ (void)(mode), NULL; })
-static inline void proc_net_remove(const char *name) {}
+#define proc_net_fops_create(net, name, mode, fops) ({ (void)(mode), NULL; })
+#define proc_net_create(net, name, mode, info) ({ (void)(mode), NULL; })
+static inline void proc_net_remove(struct net *net, const char *name) {}
static inline void proc_flush_task(struct task_struct *task) { }
@@ -281,6 +265,16 @@ static inline struct proc_dir_entry *PDE(const struct inode *inode)
return PROC_I(inode)->pde;
}
+static inline struct net *PDE_NET(struct proc_dir_entry *pde)
+{
+ return pde->parent->data;
+}
+
+static inline struct net *PROC_NET(const struct inode *inode)
+{
+ return PDE_NET(PDE(inode));
+}
+
struct proc_maps_private {
struct pid *pid;
struct task_struct *task;
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 6344b77..5472476 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -8,6 +8,7 @@
#include <linux/workqueue.h>
#include <linux/list.h>
+struct proc_dir_entry;
struct net {
atomic_t count; /* To decided when the network
* namespace should be freed.
@@ -17,6 +18,10 @@ struct net {
*/
struct list_head list; /* list of network namespaces */
struct work_struct work; /* work struct for freeing */
+
+ struct proc_dir_entry *proc_net;
+ struct proc_dir_entry *proc_net_stat;
+ struct proc_dir_entry *proc_net_root;
};
extern struct net init_net;
diff --git a/net/802/tr.c b/net/802/tr.c
index e56e61a..032c31e 100644
--- a/net/802/tr.c
+++ b/net/802/tr.c
@@ -36,6 +36,7 @@
#include <linux/seq_file.h>
#include <linux/init.h>
#include <net/arp.h>
+#include <net/net_namespace.h>
static void tr_add_rif_info(struct trh_hdr *trh, struct net_device *dev);
static void rif_check_expire(unsigned long dummy);
@@ -639,7 +640,7 @@ static int __init rif_init(void)
rif_timer.function = rif_check_expire;
add_timer(&rif_timer);
- proc_net_fops_create("tr_rif", S_IRUGO, &rif_seq_fops);
+ proc_net_fops_create(&init_net, "tr_rif", S_IRUGO, &rif_seq_fops);
return 0;
}
diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c
index bd08aa0..ac80e6b 100644
--- a/net/8021q/vlanproc.c
+++ b/net/8021q/vlanproc.c
@@ -33,6 +33,7 @@
#include <linux/fs.h>
#include <linux/netdevice.h>
#include <linux/if_vlan.h>
+#include <net/net_namespace.h>
#include "vlanproc.h"
#include "vlan.h"
@@ -143,7 +144,7 @@ void vlan_proc_cleanup(void)
remove_proc_entry(name_conf, proc_vlan_dir);
if (proc_vlan_dir)
- proc_net_remove(name_root);
+ proc_net_remove(&init_net, name_root);
/* Dynamically added entries should be cleaned up as their vlan_device
* is removed, so we should not have to take care of it here...
@@ -156,7 +157,7 @@ void vlan_proc_cleanup(void)
int __init vlan_proc_init(void)
{
- proc_vlan_dir = proc_mkdir(name_root, proc_net);
+ proc_vlan_dir = proc_mkdir(name_root, init_net.proc_net);
if (proc_vlan_dir) {
proc_vlan_conf = create_proc_entry(name_conf,
S_IFREG|S_IRUSR|S_IWUSR,
diff --git a/net/appletalk/atalk_proc.c b/net/appletalk/atalk_proc.c
index 87a582c..05d9652 100644
--- a/net/appletalk/atalk_proc.c
+++ b/net/appletalk/atalk_proc.c
@@ -11,6 +11,7 @@
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <net/net_namespace.h>
#include <net/sock.h>
#include <linux/atalk.h>
@@ -271,7 +272,7 @@ int __init atalk_proc_init(void)
struct proc_dir_entry *p;
int rc = -ENOMEM;
- atalk_proc_dir = proc_mkdir("atalk", proc_net);
+ atalk_proc_dir = proc_mkdir("atalk", init_net.proc_net);
if (!atalk_proc_dir)
goto out;
atalk_proc_dir->owner = THIS_MODULE;
@@ -306,7 +307,7 @@ out_socket:
out_route:
remove_proc_entry("interface", atalk_proc_dir);
out_interface:
- remove_proc_entry("atalk", proc_net);
+ remove_proc_entry("atalk", init_net.proc_net);
goto out;
}
@@ -316,5 +317,5 @@ void __exit atalk_proc_exit(void)
remove_proc_entry("route", atalk_proc_dir);
remove_proc_entry("socket", atalk_proc_dir);
remove_proc_entry("arp", atalk_proc_dir);
- remove_proc_entry("atalk", proc_net);
+ remove_proc_entry("atalk", init_net.proc_net);
}
diff --git a/net/atm/proc.c b/net/atm/proc.c
index 99fc1fe..3a6be64 100644
--- a/net/atm/proc.c
+++ b/net/atm/proc.c
@@ -22,6 +22,7 @@
#include <linux/netdevice.h>
#include <linux/atmclip.h>
#include <linux/init.h> /* for __init */
+#include <net/net_namespace.h>
#include <net/atmclip.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
@@ -475,7 +476,7 @@ static void atm_proc_dirs_remove(void)
if (e->dirent)
remove_proc_entry(e->name, atm_proc_root);
}
- remove_proc_entry("net/atm", NULL);
+ remove_proc_entry("atm", init_net.proc_net);
}
int __init atm_proc_init(void)
@@ -483,7 +484,7 @@ int __init atm_proc_init(void)
static struct atm_proc_entry *e;
int ret;
- atm_proc_root = proc_mkdir("net/atm",NULL);
+ atm_proc_root = proc_mkdir("atm", init_net.proc_net);
if (!atm_proc_root)
goto err_out;
for (e = atm_proc_ents; e->name; e++) {
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index dae2a42..1d71f85 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -44,6 +44,7 @@
#include <linux/sysctl.h>
#include <linux/init.h>
#include <linux/spinlock.h>
+#include <net/net_namespace.h>
#include <net/tcp_states.h>
#include <net/ip.h>
#include <net/arp.h>
@@ -1998,9 +1999,9 @@ static int __init ax25_init(void)
register_netdevice_notifier(&ax25_dev_notifier);
ax25_register_sysctl();
- proc_net_fops_create("ax25_route", S_IRUGO, &ax25_route_fops);
- proc_net_fops_create("ax25", S_IRUGO, &ax25_info_fops);
- proc_net_fops_create("ax25_calls", S_IRUGO, &ax25_uid_fops);
+ proc_net_fops_create(&init_net, "ax25_route", S_IRUGO, &ax25_route_fops);
+ proc_net_fops_create(&init_net, "ax25", S_IRUGO, &ax25_info_fops);
+ proc_net_fops_create(&init_net, "ax25_calls", S_IRUGO, &ax25_uid_fops);
out:
return rc;
}
@@ -2014,9 +2015,9 @@ MODULE_ALIAS_NETPROTO(PF_AX25);
static void __exit ax25_exit(void)
{
- proc_net_remove("ax25_route");
- proc_net_remove("ax25");
- proc_net_remove("ax25_calls");
+ proc_net_remove(&init_net, "ax25_route");
+ proc_net_remove(&init_net, "ax25");
+ proc_net_remove(&init_net, "ax25_calls");
ax25_rt_free();
ax25_uid_free();
ax25_dev_free();
diff --git a/net/core/dev.c b/net/core/dev.c
index 7d19a48..2ade518 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -92,6 +92,7 @@
#include <linux/etherdevice.h>
#include <linux/notifier.h>
#include <linux/skbuff.h>
+#include <net/net_namespace.h>
#include <net/sock.h>
#include <linux/rtnetlink.h>
#include <linux/proc_fs.h>
@@ -2538,24 +2539,24 @@ static int __init dev_proc_init(void)
{
int rc = -ENOMEM;
- if (!proc_net_fops_create("dev", S_IRUGO, &dev_seq_fops))
+ if (!proc_net_fops_create(&init_net, "dev", S_IRUGO, &dev_seq_fops))
goto out;
- if (!proc_net_fops_create("softnet_stat", S_IRUGO, &softnet_seq_fops))
+ if (!proc_net_fops_create(&init_net, "softnet_stat", S_IRUGO, &softnet_seq_fops))
goto out_dev;
- if (!proc_net_fops_create("ptype", S_IRUGO, &ptype_seq_fops))
- goto out_dev2;
+ if (!proc_net_fops_create(&init_net, "ptype", S_IRUGO, &ptype_seq_fops))
+ goto out_softnet;
if (wext_proc_init())
- goto out_softnet;
+ goto out_ptype;
rc = 0;
out:
return rc;
+out_ptype:
+ proc_net_remove(&init_net, "ptype");
out_softnet:
- proc_net_remove("ptype");
-out_dev2:
- proc_net_remove("softnet_stat");
+ proc_net_remove(&init_net, "softnet_stat");
out_dev:
- proc_net_remove("dev");
+ proc_net_remove(&init_net, "dev");
goto out;
}
#else
diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c
index 20330c5..8e069fc 100644
--- a/net/core/dev_mcast.c
+++ b/net/core/dev_mcast.c
@@ -41,6 +41,7 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/init.h>
+#include <net/net_namespace.h>
#include <net/ip.h>
#include <net/route.h>
#include <linux/skbuff.h>
@@ -254,7 +255,7 @@ static const struct file_operations dev_mc_seq_fops = {
void __init dev_mcast_init(void)
{
- proc_net_fops_create("dev_mcast", 0, &dev_mc_seq_fops);
+ proc_net_fops_create(&init_net, "dev_mcast", 0, &dev_mc_seq_fops);
}
EXPORT_SYMBOL(dev_mc_add);
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index ecd43c4..5f25f4f 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -25,6 +25,7 @@
#include <linux/sysctl.h>
#endif
#include <linux/times.h>
+#include <net/net_namespace.h>
#include <net/neighbour.h>
#include <net/dst.h>
#include <net/sock.h>
@@ -1350,7 +1351,7 @@ void neigh_table_init_no_netlink(struct neigh_table *tbl)
panic("cannot create neighbour cache statistics");
#ifdef CONFIG_PROC_FS
- tbl->pde = create_proc_entry(tbl->id, 0, proc_net_stat);
+ tbl->pde = create_proc_entry(tbl->id, 0, init_net.proc_net_stat);
if (!tbl->pde)
panic("cannot create neighbour proc dir entry");
tbl->pde->proc_fops = &neigh_stat_seq_fops;
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 6fa1821..fa15cc7 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -149,6 +149,7 @@
#include <linux/wait.h>
#include <linux/etherdevice.h>
#include <linux/kthread.h>
+#include <net/net_namespace.h>
#include <net/checksum.h>
#include <net/ipv6.h>
#include <net/addrconf.h>
@@ -3801,7 +3802,7 @@ static int __init pg_init(void)
printk(KERN_INFO "%s", version);
- pg_proc_dir = proc_mkdir(PG_PROC_DIR, proc_net);
+ pg_proc_dir = proc_mkdir(PG_PROC_DIR, init_net.proc_net);
if (!pg_proc_dir)
return -ENODEV;
pg_proc_dir->owner = THIS_MODULE;
@@ -3810,7 +3811,7 @@ static int __init pg_init(void)
if (pe == NULL) {
printk(KERN_ERR "pktgen: ERROR: cannot create %s "
"procfs entry.\n", PGCTRL);
- proc_net_remove(PG_PROC_DIR);
+ proc_net_remove(&init_net, PG_PROC_DIR);
return -EINVAL;
}
@@ -3834,7 +3835,7 @@ static int __init pg_init(void)
"all threads\n");
unregister_netdevice_notifier(&pktgen_notifier_block);
remove_proc_entry(PGCTRL, pg_proc_dir);
- proc_net_remove(PG_PROC_DIR);
+ proc_net_remove(&init_net, PG_PROC_DIR);
return -ENODEV;
}
@@ -3861,7 +3862,7 @@ static void __exit pg_cleanup(void)
/* Clean up proc file system */
remove_proc_entry(PGCTRL, pg_proc_dir);
- proc_net_remove(PG_PROC_DIR);
+ proc_net_remove(&init_net, PG_PROC_DIR);
}
module_init(pg_init);
diff --git a/net/core/sock.c b/net/core/sock.c
index cfed7d4..3d16a4b 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -119,6 +119,7 @@
#include <linux/netdevice.h>
#include <net/protocol.h>
#include <linux/skbuff.h>
+#include <net/net_namespace.h>
#include <net/request_sock.h>
#include <net/sock.h>
#include <net/xfrm.h>
@@ -1963,7 +1964,7 @@ static const struct file_operations proto_seq_fops = {
static int __init proto_init(void)
{
/* register /proc/net/protocols */
- return proc_net_fops_create("protocols", S_IRUGO, &proto_seq_fops) == NULL ? -ENOBUFS : 0;
+ return proc_net_fops_create(&init_net, "protocols", S_IRUGO, &proto_seq_fops) == NULL ? -ENOBUFS : 0;
}
subsys_initcall(proto_init);
diff --git a/net/dccp/probe.c b/net/dccp/probe.c
index bae10b0..7053bb8 100644
--- a/net/dccp/probe.c
+++ b/net/dccp/probe.c
@@ -30,6 +30,7 @@
#include <linux/module.h>
#include <linux/kfifo.h>
#include <linux/vmalloc.h>
+#include <net/net_namespace.h>
#include "dccp.h"
#include "ccid.h"
@@ -168,7 +169,7 @@ static __init int dccpprobe_init(void)
if (IS_ERR(dccpw.fifo))
return PTR_ERR(dccpw.fifo);
- if (!proc_net_fops_create(procname, S_IRUSR, &dccpprobe_fops))
+ if (!proc_net_fops_create(&init_net, procname, S_IRUSR, &dccpprobe_fops))
goto err0;
ret = register_jprobe(&dccp_send_probe);
@@ -178,7 +179,7 @@ static __init int dccpprobe_init(void)
pr_info("DCCP watch registered (port=%d)\n", port);
return 0;
err1:
- proc_net_remove(procname);
+ proc_net_remove(&init_net, procname);
err0:
kfifo_free(dccpw.fifo);
return ret;
@@ -188,7 +189,7 @@ module_init(dccpprobe_init);
static __exit void dccpprobe_exit(void)
{
kfifo_free(dccpw.fifo);
- proc_net_remove(procname);
+ proc_net_remove(&init_net, procname);
unregister_jprobe(&dccp_send_probe);
}
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
index ed76d4a..625d595 100644
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -128,6 +128,7 @@ Version 0.0.6 2.1.110 07-aug-98 Eduardo Marcelo Serrat
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/poll.h>
+#include <net/net_namespace.h>
#include <net/neighbour.h>
#include <net/dst.h>
#include <net/fib_rules.h>
@@ -2399,7 +2400,7 @@ static int __init decnet_init(void)
dev_add_pack(&dn_dix_packet_type);
register_netdevice_notifier(&dn_dev_notifier);
- proc_net_fops_create("decnet", S_IRUGO, &dn_socket_seq_fops);
+ proc_net_fops_create(&init_net, "decnet", S_IRUGO, &dn_socket_seq_fops);
dn_register_sysctl();
out:
return rc;
@@ -2428,7 +2429,7 @@ static void __exit decnet_exit(void)
dn_neigh_cleanup();
dn_fib_cleanup();
- proc_net_remove("decnet");
+ proc_net_remove(&init_net, "decnet");
proto_unregister(&dn_proto);
}
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index fa6604f..04f12e2 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -42,6 +42,7 @@
#include <linux/notifier.h>
#include <asm/uaccess.h>
#include <asm/system.h>
+#include <net/net_namespace.h>
#include <net/neighbour.h>
#include <net/dst.h>
#include <net/flow.h>
@@ -1462,7 +1463,7 @@ void __init dn_dev_init(void)
rtnl_register(PF_DECnet, RTM_DELADDR, dn_nl_deladdr, NULL);
rtnl_register(PF_DECnet, RTM_GETADDR, NULL, dn_nl_dump_ifaddr);
- proc_net_fops_create("decnet_dev", S_IRUGO, &dn_dev_seq_fops);
+ proc_net_fops_create(&init_net, "decnet_dev", S_IRUGO, &dn_dev_seq_fops);
#ifdef CONFIG_SYSCTL
{
@@ -1483,7 +1484,7 @@ void __exit dn_dev_cleanup(void)
}
#endif /* CONFIG_SYSCTL */
- proc_net_remove("decnet_dev");
+ proc_net_remove(&init_net, "decnet_dev");
dn_dev_devices_off();
}
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c
index 174d8a7..a424a8d 100644
--- a/net/decnet/dn_neigh.c
+++ b/net/decnet/dn_neigh.c
@@ -38,6 +38,7 @@
#include <linux/rcupdate.h>
#include <linux/jhash.h>
#include <asm/atomic.h>
+#include <net/net_namespace.h>
#include <net/neighbour.h>
#include <net/dst.h>
#include <net/flow.h>
@@ -611,11 +612,11 @@ static const struct file_operations dn_neigh_seq_fops = {
void __init dn_neigh_init(void)
{
neigh_table_init(&dn_neigh_table);
- proc_net_fops_create("decnet_neigh", S_IRUGO, &dn_neigh_seq_fops);
+ proc_net_fops_create(&init_net, "decnet_neigh", S_IRUGO, &dn_neigh_seq_fops);
}
void __exit dn_neigh_cleanup(void)
{
- proc_net_remove("decnet_neigh");
+ proc_net_remove(&init_net, "decnet_neigh");
neigh_table_clear(&dn_neigh_table);
}
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index a4a6209..4cfea95 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -77,6 +77,7 @@
#include <linux/rcupdate.h>
#include <linux/times.h>
#include <asm/errno.h>
+#include <net/net_namespace.h>
#include <net/netlink.h>
#include <net/neighbour.h>
#include <net/dst.h>
@@ -1814,7 +1815,7 @@ void __init dn_route_init(void)
dn_dst_ops.gc_thresh = (dn_rt_hash_mask + 1);
- proc_net_fops_create("decnet_cache", S_IRUGO, &dn_rt_cache_seq_fops);
+ proc_net_fops_create(&init_net, "decnet_cache", S_IRUGO, &dn_rt_cache_seq_fops);
#ifdef CONFIG_DECNET_ROUTER
rtnl_register(PF_DECnet, RTM_GETROUTE, dn_cache_getroute, dn_fib_dump);
@@ -1829,6 +1830,6 @@ void __exit dn_route_cleanup(void)
del_timer(&dn_route_timer);
dn_run_flush(0);
- proc_net_remove("decnet_cache");
+ proc_net_remove(&init_net, "decnet_cache");
}
diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c
index 17ad278..69cb6aa 100644
--- a/net/ieee80211/ieee80211_module.c
+++ b/net/ieee80211/ieee80211_module.c
@@ -47,6 +47,7 @@
#include <linux/wireless.h>
#include <linux/etherdevice.h>
#include <asm/uaccess.h>
+#include <net/net_namespace.h>
#include <net/arp.h>
#include <net/ieee80211.h>
@@ -264,7 +265,7 @@ static int __init ieee80211_init(void)
struct proc_dir_entry *e;
ieee80211_debug_level = debug;
- ieee80211_proc = proc_mkdir(DRV_NAME, proc_net);
+ ieee80211_proc = proc_mkdir(DRV_NAME, init_net.proc_net);
if (ieee80211_proc == NULL) {
IEEE80211_ERROR("Unable to create " DRV_NAME
" proc directory\n");
@@ -273,7 +274,7 @@ static int __init ieee80211_init(void)
e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
ieee80211_proc);
if (!e) {
- remove_proc_entry(DRV_NAME, proc_net);
+ remove_proc_entry(DRV_NAME, init_net.proc_net);
ieee80211_proc = NULL;
return -EIO;
}
@@ -293,7 +294,7 @@ static void __exit ieee80211_exit(void)
#ifdef CONFIG_IEEE80211_DEBUG
if (ieee80211_proc) {
remove_proc_entry("debug_level", ieee80211_proc);
- remove_proc_entry(DRV_NAME, proc_net);
+ remove_proc_entry(DRV_NAME, init_net.proc_net);
ieee80211_proc = NULL;
}
#endif /* CONFIG_IEEE80211_DEBUG */
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 9ab9d53..78dd344 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -103,6 +103,7 @@
#include <linux/sysctl.h>
#endif
+#include <net/net_namespace.h>
#include <net/ip.h>
#include <net/icmp.h>
#include <net/route.h>
@@ -1400,7 +1401,7 @@ static const struct file_operations arp_seq_fops = {
static int __init arp_proc_init(void)
{
- if (!proc_net_fops_create("arp", S_IRUGO, &arp_seq_fops))
+ if (!proc_net_fops_create(&init_net, "arp", S_IRUGO, &arp_seq_fops))
return -ENOMEM;
return 0;
}
diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c
index 9ad1d9f..9fafbee 100644
--- a/net/ipv4/fib_hash.c
+++ b/net/ipv4/fib_hash.c
@@ -35,6 +35,7 @@
#include <linux/netlink.h>
#include <linux/init.h>
+#include <net/net_namespace.h>
#include <net/ip.h>
#include <net/protocol.h>
#include <net/route.h>
@@ -1068,13 +1069,13 @@ static const struct file_operations fib_seq_fops = {
int __init fib_proc_init(void)
{
- if (!proc_net_fops_create("route", S_IRUGO, &fib_seq_fops))
+ if (!proc_net_fops_create(&init_net, "route", S_IRUGO, &fib_seq_fops))
return -ENOMEM;
return 0;
}
void __init fib_proc_exit(void)
{
- proc_net_remove("route");
+ proc_net_remove(&init_net, "route");
}
#endif /* CONFIG_PROC_FS */
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 52b2891..be34bd5 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -73,6 +73,7 @@
#include <linux/netlink.h>
#include <linux/init.h>
#include <linux/list.h>
+#include <net/net_namespace.h>
#include <net/ip.h>
#include <net/protocol.h>
#include <net/route.h>
@@ -2530,30 +2531,30 @@ static const struct file_operations fib_route_fops = {
int __init fib_proc_init(void)
{
- if (!proc_net_fops_create("fib_trie", S_IRUGO, &fib_trie_fops))
+ if (!proc_net_fops_create(&init_net, "fib_trie", S_IRUGO, &fib_trie_fops))
goto out1;
- if (!proc_net_fops_create("fib_triestat", S_IRUGO, &fib_triestat_fops))
+ if (!proc_net_fops_create(&init_net, "fib_triestat", S_IRUGO, &fib_triestat_fops))
goto out2;
- if (!proc_net_fops_create("route", S_IRUGO, &fib_route_fops))
+ if (!proc_net_fops_create(&init_net, "route", S_IRUGO, &fib_route_fops))
goto out3;
return 0;
out3:
- proc_net_remove("fib_triestat");
+ proc_net_remove(&init_net, "fib_triestat");
out2:
- proc_net_remove("fib_trie");
+ proc_net_remove(&init_net, "fib_trie");
out1:
return -ENOMEM;
}
void __init fib_proc_exit(void)
{
- proc_net_remove("fib_trie");
- proc_net_remove("fib_triestat");
- proc_net_remove("route");
+ proc_net_remove(&init_net, "fib_trie");
+ proc_net_remove(&init_net, "fib_triestat");
+ proc_net_remove(&init_net, "route");
}
#endif /* CONFIG_PROC_FS */
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index a646409..d78599a 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -91,6 +91,7 @@
#include <linux/rtnetlink.h>
#include <linux/times.h>
+#include <net/net_namespace.h>
#include <net/arp.h>
#include <net/ip.h>
#include <net/protocol.h>
@@ -2613,8 +2614,8 @@ static const struct file_operations igmp_mcf_seq_fops = {
int __init igmp_mc_proc_init(void)
{
- proc_net_fops_create("igmp", S_IRUGO, &igmp_mc_seq_fops);
- proc_net_fops_create("mcfilter", S_IRUGO, &igmp_mcf_seq_fops);
+ proc_net_fops_create(&init_net, "igmp", S_IRUGO, &igmp_mc_seq_fops);
+ proc_net_fops_create(&init_net, "mcfilter", S_IRUGO, &igmp_mcf_seq_fops);
return 0;
}
#endif
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index c5b2470..5ae4849 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -55,6 +55,7 @@
#include <linux/root_dev.h>
#include <linux/delay.h>
#include <linux/nfs_fs.h>
+#include <net/net_namespace.h>
#include <net/arp.h>
#include <net/ip.h>
#include <net/ipconfig.h>
@@ -1253,7 +1254,7 @@ static int __init ip_auto_config(void)
__be32 addr;
#ifdef CONFIG_PROC_FS
- proc_net_fops_create("pnp", S_IRUGO, &pnp_seq_fops);
+ proc_net_fops_create(&init_net, "pnp", S_IRUGO, &pnp_seq_fops);
#endif /* CONFIG_PROC_FS */
if (!ic_enable)
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 7003cc1..35683e1 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -49,6 +49,7 @@
#include <linux/mroute.h>
#include <linux/init.h>
#include <linux/if_ether.h>
+#include <net/net_namespace.h>
#include <net/ip.h>
#include <net/protocol.h>
#include <linux/skbuff.h>
@@ -1922,7 +1923,7 @@ void __init ip_mr_init(void)
ipmr_expire_timer.function=ipmr_expire_process;
register_netdevice_notifier(&ip_mr_notifier);
#ifdef CONFIG_PROC_FS
- proc_net_fops_create("ip_mr_vif", 0, &ipmr_vif_fops);
- proc_net_fops_create("ip_mr_cache", 0, &ipmr_mfc_fops);
+ proc_net_fops_create(&init_net, "ip_mr_vif", 0, &ipmr_vif_fops);
+ proc_net_fops_create(&init_net, "ip_mr_cache", 0, &ipmr_mfc_fops);
#endif
}
diff --git a/net/ipv4/ipvs/ip_vs_app.c b/net/ipv4/ipvs/ip_vs_app.c
index 8d6901d..341474e 100644
--- a/net/ipv4/ipvs/ip_vs_app.c
+++ b/net/ipv4/ipvs/ip_vs_app.c
@@ -25,6 +25,7 @@
#include <linux/skbuff.h>
#include <linux/in.h>
#include <linux/ip.h>
+#include <net/net_namespace.h>
#include <net/protocol.h>
#include <net/tcp.h>
#include <asm/system.h>
@@ -616,12 +617,12 @@ int ip_vs_skb_replace(struct sk_buff *skb, gfp_t pri,
int ip_vs_app_init(void)
{
/* we will replace it with proc_net_ipvs_create() soon */
- proc_net_fops_create("ip_vs_app", 0, &ip_vs_app_fops);
+ proc_net_fops_create(&init_net, "ip_vs_app", 0, &ip_vs_app_fops);
return 0;
}
void ip_vs_app_cleanup(void)
{
- proc_net_remove("ip_vs_app");
+ proc_net_remove(&init_net, "ip_vs_app");
}
diff --git a/net/ipv4/ipvs/ip_vs_conn.c b/net/ipv4/ipvs/ip_vs_conn.c
index d612a6a..4b702f7 100644
--- a/net/ipv4/ipvs/ip_vs_conn.c
+++ b/net/ipv4/ipvs/ip_vs_conn.c
@@ -35,6 +35,7 @@
#include <linux/jhash.h>
#include <linux/random.h>
+#include <net/net_namespace.h>
#include <net/ip_vs.h>
@@ -922,7 +923,7 @@ int ip_vs_conn_init(void)
rwlock_init(&__ip_vs_conntbl_lock_array[idx].l);
}
- proc_net_fops_create("ip_vs_conn", 0, &ip_vs_conn_fops);
+ proc_net_fops_create(&init_net, "ip_vs_conn", 0, &ip_vs_conn_fops);
/* calculate the random value for connection hash */
get_random_bytes(&ip_vs_conn_rnd, sizeof(ip_vs_conn_rnd));
@@ -938,6 +939,6 @@ void ip_vs_conn_cleanup(void)
/* Release the empty cache */
kmem_cache_destroy(ip_vs_conn_cachep);
- proc_net_remove("ip_vs_conn");
+ proc_net_remove(&init_net, "ip_vs_conn");
vfree(ip_vs_conn_tab);
}
diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c
index 902fd57..a5f2703 100644
--- a/net/ipv4/ipvs/ip_vs_ctl.c
+++ b/net/ipv4/ipvs/ip_vs_ctl.c
@@ -35,6 +35,7 @@
#include <linux/netfilter_ipv4.h>
#include <linux/mutex.h>
+#include <net/net_namespace.h>
#include <net/ip.h>
#include <net/route.h>
#include <net/sock.h>
@@ -2355,8 +2356,8 @@ int ip_vs_control_init(void)
return ret;
}
- proc_net_fops_create("ip_vs", 0, &ip_vs_info_fops);
- proc_net_fops_create("ip_vs_stats",0, &ip_vs_stats_fops);
+ proc_net_fops_create(&init_net, "ip_vs", 0, &ip_vs_info_fops);
+ proc_net_fops_create(&init_net, "ip_vs_stats",0, &ip_vs_stats_fops);
sysctl_header = register_sysctl_table(vs_root_table);
@@ -2389,8 +2390,8 @@ void ip_vs_control_cleanup(void)
cancel_work_sync(&defense_work.work);
ip_vs_kill_estimator(&ip_vs_stats);
unregister_sysctl_table(sysctl_header);
- proc_net_remove("ip_vs_stats");
- proc_net_remove("ip_vs");
+ proc_net_remove(&init_net, "ip_vs_stats");
+ proc_net_remove(&init_net, "ip_vs");
nf_unregister_sockopt(&ip_vs_sockopts);
LeaveFunction(2);
}
diff --git a/net/ipv4/ipvs/ip_vs_lblcr.c b/net/ipv4/ipvs/ip_vs_lblcr.c
index 6225aca..6a1fec4 100644
--- a/net/ipv4/ipvs/ip_vs_lblcr.c
+++ b/net/ipv4/ipvs/ip_vs_lblcr.c
@@ -50,6 +50,7 @@
#include <linux/sysctl.h>
/* for proc_net_create/proc_net_remove */
#include <linux/proc_fs.h>
+#include <net/net_namespace.h>
#include <net/ip_vs.h>
@@ -843,7 +844,7 @@ static int __init ip_vs_lblcr_init(void)
INIT_LIST_HEAD(&ip_vs_lblcr_scheduler.n_list);
sysctl_header = register_sysctl_table(lblcr_root_table);
#ifdef CONFIG_IP_VS_LBLCR_DEBUG
- proc_net_create("ip_vs_lblcr", 0, ip_vs_lblcr_getinfo);
+ proc_net_create(&init_net, "ip_vs_lblcr", 0, ip_vs_lblcr_getinfo);
#endif
return register_ip_vs_scheduler(&ip_vs_lblcr_scheduler);
}
@@ -852,7 +853,7 @@ static int __init ip_vs_lblcr_init(void)
static void __exit ip_vs_lblcr_cleanup(void)
{
#ifdef CONFIG_IP_VS_LBLCR_DEBUG
- proc_net_remove("ip_vs_lblcr");
+ proc_net_remove(&init_net, "ip_vs_lblcr");
#endif
unregister_sysctl_table(sysctl_header);
unregister_ip_vs_scheduler(&ip_vs_lblcr_scheduler);
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index 702d94d..cb5e61a 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -24,6 +24,7 @@
#include <linux/proc_fs.h>
#include <linux/security.h>
#include <linux/mutex.h>
+#include <net/net_namespace.h>
#include <net/sock.h>
#include <net/route.h>
@@ -674,7 +675,7 @@ static int __init ip_queue_init(void)
goto cleanup_netlink_notifier;
}
- proc = proc_net_create(IPQ_PROC_FS_NAME, 0, ipq_get_info);
+ proc = proc_net_create(&init_net, IPQ_PROC_FS_NAME, 0, ipq_get_info);
if (proc)
proc->owner = THIS_MODULE;
else {
@@ -695,8 +696,7 @@ static int __init ip_queue_init(void)
cleanup_sysctl:
unregister_sysctl_table(ipq_sysctl_header);
unregister_netdevice_notifier(&ipq_dev_notifier);
- proc_net_remove(IPQ_PROC_FS_NAME);
-
+ proc_net_remove(&init_net, IPQ_PROC_FS_NAME);
cleanup_ipqnl:
sock_release(ipqnl->sk_socket);
mutex_lock(&ipqnl_mutex);
@@ -715,7 +715,7 @@ static void __exit ip_queue_fini(void)
unregister_sysctl_table(ipq_sysctl_header);
unregister_netdevice_notifier(&ipq_dev_notifier);
- proc_net_remove(IPQ_PROC_FS_NAME);
+ proc_net_remove(&init_net, IPQ_PROC_FS_NAME);
sock_release(ipqnl->sk_socket);
mutex_lock(&ipqnl_mutex);
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 69bd362..50fc9e0 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -25,6 +25,7 @@
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv4/ipt_CLUSTERIP.h>
#include <net/netfilter/nf_conntrack.h>
+#include <net/net_namespace.h>
#include <net/checksum.h>
#define CLUSTERIP_VERSION "0.8"
@@ -726,7 +727,7 @@ static int __init ipt_clusterip_init(void)
goto cleanup_target;
#ifdef CONFIG_PROC_FS
- clusterip_procdir = proc_mkdir("ipt_CLUSTERIP", proc_net);
+ clusterip_procdir = proc_mkdir("ipt_CLUSTERIP", init_net.proc_net);
if (!clusterip_procdir) {
printk(KERN_ERR "CLUSTERIP: Unable to proc dir entry\n");
ret = -ENOMEM;
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c
index 6d0c0f7..db2a798 100644
--- a/net/ipv4/netfilter/ipt_recent.c
+++ b/net/ipv4/netfilter/ipt_recent.c
@@ -24,6 +24,7 @@
#include <linux/bitops.h>
#include <linux/skbuff.h>
#include <linux/inet.h>
+#include <net/net_namespace.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_ipv4/ipt_recent.h>
@@ -487,7 +488,7 @@ static int __init ipt_recent_init(void)
#ifdef CONFIG_PROC_FS
if (err)
return err;
- proc_dir = proc_mkdir("ipt_recent", proc_net);
+ proc_dir = proc_mkdir("ipt_recent", init_net.proc_net);
if (proc_dir == NULL) {
xt_unregister_match(&recent_match);
err = -ENOMEM;
@@ -501,7 +502,7 @@ static void __exit ipt_recent_exit(void)
BUG_ON(!list_empty(&tables));
xt_unregister_match(&recent_match);
#ifdef CONFIG_PROC_FS
- remove_proc_entry("ipt_recent", proc_net);
+ remove_proc_entry("ipt_recent", init_net.proc_net);
#endif
}
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
index b3dd5de..a5ae2ea 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
@@ -11,6 +11,7 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/percpu.h>
+#include <net/net_namespace.h>
#include <linux/netfilter.h>
#include <net/netfilter/nf_conntrack_core.h>
@@ -408,16 +409,16 @@ int __init nf_conntrack_ipv4_compat_init(void)
{
struct proc_dir_entry *proc, *proc_exp, *proc_stat;
- proc = proc_net_fops_create("ip_conntrack", 0440, &ct_file_ops);
+ proc = proc_net_fops_create(&init_net, "ip_conntrack", 0440, &ct_file_ops);
if (!proc)
goto err1;
- proc_exp = proc_net_fops_create("ip_conntrack_expect", 0440,
+ proc_exp = proc_net_fops_create(&init_net, "ip_conntrack_expect", 0440,
&ip_exp_file_ops);
if (!proc_exp)
goto err2;
- proc_stat = create_proc_entry("ip_conntrack", S_IRUGO, proc_net_stat);
+ proc_stat = create_proc_entry("ip_conntrack", S_IRUGO, init_net.proc_net_stat);
if (!proc_stat)
goto err3;
@@ -427,16 +428,16 @@ int __init nf_conntrack_ipv4_compat_init(void)
return 0;
err3:
- proc_net_remove("ip_conntrack_expect");
+ proc_net_remove(&init_net, "ip_conntrack_expect");
err2:
- proc_net_remove("ip_conntrack");
+ proc_net_remove(&init_net, "ip_conntrack");
err1:
return -ENOMEM;
}
void __exit nf_conntrack_ipv4_compat_fini(void)
{
- remove_proc_entry("ip_conntrack", proc_net_stat);
- proc_net_remove("ip_conntrack_expect");
- proc_net_remove("ip_conntrack");
+ remove_proc_entry("ip_conntrack", init_net.proc_net_stat);
+ proc_net_remove(&init_net, "ip_conntrack_expect");
+ proc_net_remove(&init_net, "ip_conntrack");
}
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index 986d1c8..95a8f8f 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -34,6 +34,7 @@
* 2 of the License, or (at your option) any later version.
*/
#include <linux/types.h>
+#include <net/net_namespace.h>
#include <net/icmp.h>
#include <net/protocol.h>
#include <net/tcp.h>
@@ -383,20 +384,20 @@ int __init ip_misc_proc_init(void)
{
int rc = 0;
- if (!proc_net_fops_create("netstat", S_IRUGO, &netstat_seq_fops))
+ if (!proc_net_fops_create(&init_net, "netstat", S_IRUGO, &netstat_seq_fops))
goto out_netstat;
- if (!proc_net_fops_create("snmp", S_IRUGO, &snmp_seq_fops))
+ if (!proc_net_fops_create(&init_net, "snmp", S_IRUGO, &snmp_seq_fops))
goto out_snmp;
- if (!proc_net_fops_create("sockstat", S_IRUGO, &sockstat_seq_fops))
+ if (!proc_net_fops_create(&init_net, "sockstat", S_IRUGO, &sockstat_seq_fops))
goto out_sockstat;
out:
return rc;
out_sockstat:
- proc_net_remove("snmp");
+ proc_net_remove(&init_net, "snmp");
out_snmp:
- proc_net_remove("netstat");
+ proc_net_remove(&init_net, "netstat");
out_netstat:
rc = -ENOMEM;
goto out;
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index c6d7152..216e01b 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -59,6 +59,7 @@
#include <linux/in_route.h>
#include <linux/route.h>
#include <linux/skbuff.h>
+#include <net/net_namespace.h>
#include <net/dst.h>
#include <net/sock.h>
#include <linux/gfp.h>
@@ -928,13 +929,13 @@ static const struct file_operations raw_seq_fops = {
int __init raw_proc_init(void)
{
- if (!proc_net_fops_create("raw", S_IRUGO, &raw_seq_fops))
+ if (!proc_net_fops_create(&init_net, "raw", S_IRUGO, &raw_seq_fops))
return -ENOMEM;
return 0;
}
void __init raw_proc_exit(void)
{
- proc_net_remove("raw");
+ proc_net_remove(&init_net, "raw");
}
#endif /* CONFIG_PROC_FS */
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index c7ca94b..efd2a92 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -91,6 +91,7 @@
#include <linux/jhash.h>
#include <linux/rcupdate.h>
#include <linux/times.h>
+#include <net/net_namespace.h>
#include <net/protocol.h>
#include <net/ip.h>
#include <net/route.h>
@@ -3011,15 +3012,15 @@ int __init ip_rt_init(void)
#ifdef CONFIG_PROC_FS
{
struct proc_dir_entry *rtstat_pde = NULL; /* keep gcc happy */
- if (!proc_net_fops_create("rt_cache", S_IRUGO, &rt_cache_seq_fops) ||
+ if (!proc_net_fops_create(&init_net, "rt_cache", S_IRUGO, &rt_cache_seq_fops) ||
!(rtstat_pde = create_proc_entry("rt_cache", S_IRUGO,
- proc_net_stat))) {
+ init_net.proc_net_stat))) {
return -ENOMEM;
}
rtstat_pde->proc_fops = &rt_cpu_seq_fops;
}
#ifdef CONFIG_NET_CLS_ROUTE
- create_proc_read_entry("rt_acct", 0, proc_net, ip_rt_acct_read, NULL);
+ create_proc_read_entry("rt_acct", 0, init_net.proc_net, ip_rt_acct_read, NULL);
#endif
#endif
#ifdef CONFIG_XFRM
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 9c94627..7fed0a6 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -62,6 +62,7 @@
#include <linux/init.h>
#include <linux/times.h>
+#include <net/net_namespace.h>
#include <net/icmp.h>
#include <net/inet_hashtables.h>
#include <net/tcp.h>
@@ -2250,7 +2251,7 @@ int tcp_proc_register(struct tcp_seq_afinfo *afinfo)
afinfo->seq_fops->llseek = seq_lseek;
afinfo->seq_fops->release = seq_release_private;
- p = proc_net_fops_create(afinfo->name, S_IRUGO, afinfo->seq_fops);
+ p = proc_net_fops_create(&init_net, afinfo->name, S_IRUGO, afinfo->seq_fops);
if (p)
p->data = afinfo;
else
@@ -2262,7 +2263,7 @@ void tcp_proc_unregister(struct tcp_seq_afinfo *afinfo)
{
if (!afinfo)
return;
- proc_net_remove(afinfo->name);
+ proc_net_remove(&init_net, afinfo->name);
memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops));
}
diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c
index b76398d..87dd5bf 100644
--- a/net/ipv4/tcp_probe.c
+++ b/net/ipv4/tcp_probe.c
@@ -26,6 +26,7 @@
#include <linux/module.h>
#include <linux/ktime.h>
#include <linux/time.h>
+#include <net/net_namespace.h>
#include <net/tcp.h>
@@ -228,7 +229,7 @@ static __init int tcpprobe_init(void)
if (!tcp_probe.log)
goto err0;
- if (!proc_net_fops_create(procname, S_IRUSR, &tcpprobe_fops))
+ if (!proc_net_fops_create(&init_net, procname, S_IRUSR, &tcpprobe_fops))
goto err0;
ret = register_jprobe(&tcp_jprobe);
@@ -238,7 +239,7 @@ static __init int tcpprobe_init(void)
pr_info("TCP probe registered (port=%d)\n", port);
return 0;
err1:
- proc_net_remove(procname);
+ proc_net_remove(&init_net, procname);
err0:
kfree(tcp_probe.log);
return ret;
@@ -247,7 +248,7 @@ module_init(tcpprobe_init);
static __exit void tcpprobe_exit(void)
{
- proc_net_remove(procname);
+ proc_net_remove(&init_net, procname);
unregister_jprobe(&tcp_jprobe);
kfree(tcp_probe.log);
}
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 4beeea8..c0c695a 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -98,6 +98,7 @@
#include <linux/skbuff.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <net/net_namespace.h>
#include <net/icmp.h>
#include <net/route.h>
#include <net/checksum.h>
@@ -1566,7 +1567,7 @@ int udp_proc_register(struct udp_seq_afinfo *afinfo)
afinfo->seq_fops->llseek = seq_lseek;
afinfo->seq_fops->release = seq_release_private;
- p = proc_net_fops_create(afinfo->name, S_IRUGO, afinfo->seq_fops);
+ p = proc_net_fops_create(&init_net, afinfo->name, S_IRUGO, afinfo->seq_fops);
if (p)
p->data = afinfo;
else
@@ -1578,7 +1579,7 @@ void udp_proc_unregister(struct udp_seq_afinfo *afinfo)
{
if (!afinfo)
return;
- proc_net_remove(afinfo->name);
+ proc_net_remove(&init_net, afinfo->name);
memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops));
}
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 91ef3be..5e62ee5 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -62,6 +62,7 @@
#include <linux/notifier.h>
#include <linux/string.h>
+#include <net/net_namespace.h>
#include <net/sock.h>
#include <net/snmp.h>
@@ -2827,14 +2828,14 @@ static const struct file_operations if6_fops = {
int __init if6_proc_init(void)
{
- if (!proc_net_fops_create("if_inet6", S_IRUGO, &if6_fops))
+ if (!proc_net_fops_create(&init_net, "if_inet6", S_IRUGO, &if6_fops))
return -ENOMEM;
return 0;
}
void if6_proc_exit(void)
{
- proc_net_remove("if_inet6");
+ proc_net_remove(&init_net, "if_inet6");
}
#endif /* CONFIG_PROC_FS */
@@ -4293,6 +4294,6 @@ void __exit addrconf_cleanup(void)
rtnl_unlock();
#ifdef CONFIG_PROC_FS
- proc_net_remove("if_inet6");
+ proc_net_remove(&init_net, "if_inet6");
#endif
}
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
index b8c533f..0bd6654 100644
--- a/net/ipv6/anycast.c
+++ b/net/ipv6/anycast.c
@@ -30,6 +30,7 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <net/net_namespace.h>
#include <net/sock.h>
#include <net/snmp.h>
@@ -578,7 +579,7 @@ static const struct file_operations ac6_seq_fops = {
int __init ac6_proc_init(void)
{
- if (!proc_net_fops_create("anycast6", S_IRUGO, &ac6_seq_fops))
+ if (!proc_net_fops_create(&init_net, "anycast6", S_IRUGO, &ac6_seq_fops))
return -ENOMEM;
return 0;
@@ -586,7 +587,7 @@ int __init ac6_proc_init(void)
void ac6_proc_exit(void)
{
- proc_net_remove("anycast6");
+ proc_net_remove(&init_net, "anycast6");
}
#endif
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index 413a4eb..1791399 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -21,6 +21,7 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <net/net_namespace.h>
#include <net/sock.h>
#include <net/ipv6.h>
@@ -690,7 +691,7 @@ static const struct file_operations ip6fl_seq_fops = {
void ip6_flowlabel_init(void)
{
#ifdef CONFIG_PROC_FS
- proc_net_fops_create("ip6_flowlabel", S_IRUGO, &ip6fl_seq_fops);
+ proc_net_fops_create(&init_net, "ip6_flowlabel", S_IRUGO, &ip6fl_seq_fops);
#endif
}
@@ -698,6 +699,6 @@ void ip6_flowlabel_cleanup(void)
{
del_timer(&ip6_fl_gc_timer);
#ifdef CONFIG_PROC_FS
- proc_net_remove("ip6_flowlabel");
+ proc_net_remove(&init_net, "ip6_flowlabel");
#endif
}
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index ae98818..a41d5a0 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -49,6 +49,7 @@
#include <linux/netfilter.h>
#include <linux/netfilter_ipv6.h>
+#include <net/net_namespace.h>
#include <net/sock.h>
#include <net/snmp.h>
@@ -2658,8 +2659,8 @@ int __init igmp6_init(struct net_proto_family *ops)
np->hop_limit = 1;
#ifdef CONFIG_PROC_FS
- proc_net_fops_create("igmp6", S_IRUGO, &igmp6_mc_seq_fops);
- proc_net_fops_create("mcfilter6", S_IRUGO, &igmp6_mcf_seq_fops);
+ proc_net_fops_create(&init_net, "igmp6", S_IRUGO, &igmp6_mc_seq_fops);
+ proc_net_fops_create(&init_net, "mcfilter6", S_IRUGO, &igmp6_mcf_seq_fops);
#endif
return 0;
@@ -2671,7 +2672,7 @@ void igmp6_cleanup(void)
igmp6_socket = NULL; /* for safety */
#ifdef CONFIG_PROC_FS
- proc_net_remove("mcfilter6");
- proc_net_remove("igmp6");
+ proc_net_remove(&init_net, "mcfilter6");
+ proc_net_remove(&init_net, "igmp6");
#endif
}
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index 0004db3..dfc58fb 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -24,6 +24,7 @@
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
#include <linux/mutex.h>
+#include <net/net_namespace.h>
#include <net/sock.h>
#include <net/ipv6.h>
#include <net/ip6_route.h>
@@ -664,7 +665,7 @@ static int __init ip6_queue_init(void)
goto cleanup_netlink_notifier;
}
- proc = proc_net_create(IPQ_PROC_FS_NAME, 0, ipq_get_info);
+ proc = proc_net_create(&init_net, IPQ_PROC_FS_NAME, 0, ipq_get_info);
if (proc)
proc->owner = THIS_MODULE;
else {
@@ -685,7 +686,7 @@ static int __init ip6_queue_init(void)
cleanup_sysctl:
unregister_sysctl_table(ipq_sysctl_header);
unregister_netdevice_notifier(&ipq_dev_notifier);
- proc_net_remove(IPQ_PROC_FS_NAME);
+ proc_net_remove(&init_net, IPQ_PROC_FS_NAME);
cleanup_ipqnl:
sock_release(ipqnl->sk_socket);
@@ -705,7 +706,7 @@ static void __exit ip6_queue_fini(void)
unregister_sysctl_table(ipq_sysctl_header);
unregister_netdevice_notifier(&ipq_dev_notifier);
- proc_net_remove(IPQ_PROC_FS_NAME);
+ proc_net_remove(&init_net, IPQ_PROC_FS_NAME);
sock_release(ipqnl->sk_socket);
mutex_lock(&ipqnl_mutex);
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index 920dc9c..a712a22 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -23,6 +23,7 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stddef.h>
+#include <net/net_namespace.h>
#include <net/ip.h>
#include <net/sock.h>
#include <net/tcp.h>
@@ -231,22 +232,22 @@ int __init ipv6_misc_proc_init(void)
{
int rc = 0;
- if (!proc_net_fops_create("snmp6", S_IRUGO, &snmp6_seq_fops))
+ if (!proc_net_fops_create(&init_net, "snmp6", S_IRUGO, &snmp6_seq_fops))
goto proc_snmp6_fail;
- proc_net_devsnmp6 = proc_mkdir("dev_snmp6", proc_net);
+ proc_net_devsnmp6 = proc_mkdir("dev_snmp6", init_net.proc_net);
if (!proc_net_devsnmp6)
goto proc_dev_snmp6_fail;
- if (!proc_net_fops_create("sockstat6", S_IRUGO, &sockstat6_seq_fops))
+ if (!proc_net_fops_create(&init_net, "sockstat6", S_IRUGO, &sockstat6_seq_fops))
goto proc_sockstat6_fail;
out:
return rc;
proc_sockstat6_fail:
- proc_net_remove("dev_snmp6");
+ proc_net_remove(&init_net, "dev_snmp6");
proc_dev_snmp6_fail:
- proc_net_remove("snmp6");
+ proc_net_remove(&init_net, "snmp6");
proc_snmp6_fail:
rc = -ENOMEM;
goto out;
@@ -254,8 +255,8 @@ proc_snmp6_fail:
void ipv6_misc_proc_exit(void)
{
- proc_net_remove("sockstat6");
- proc_net_remove("dev_snmp6");
- proc_net_remove("snmp6");
+ proc_net_remove(&init_net, "sockstat6");
+ proc_net_remove(&init_net, "dev_snmp6");
+ proc_net_remove(&init_net, "snmp6");
}
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index e27383d..20c1a76 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -35,6 +35,7 @@
#include <asm/uaccess.h>
#include <asm/ioctls.h>
+#include <net/net_namespace.h>
#include <net/ip.h>
#include <net/sock.h>
#include <net/snmp.h>
@@ -1316,13 +1317,13 @@ static const struct file_operations raw6_seq_fops = {
int __init raw6_proc_init(void)
{
- if (!proc_net_fops_create("raw6", S_IRUGO, &raw6_seq_fops))
+ if (!proc_net_fops_create(&init_net, "raw6", S_IRUGO, &raw6_seq_fops))
return -ENOMEM;
return 0;
}
void raw6_proc_exit(void)
{
- proc_net_remove("raw6");
+ proc_net_remove(&init_net, "raw6");
}
#endif /* CONFIG_PROC_FS */
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 55ea80f..f4f0c34 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -44,6 +44,7 @@
#include <linux/seq_file.h>
#endif
+#include <net/net_namespace.h>
#include <net/snmp.h>
#include <net/ipv6.h>
#include <net/ip6_fib.h>
@@ -2561,11 +2562,11 @@ void __init ip6_route_init(void)
fib6_init();
#ifdef CONFIG_PROC_FS
- p = proc_net_create("ipv6_route", 0, rt6_proc_info);
+ p = proc_net_create(&init_net, "ipv6_route", 0, rt6_proc_info);
if (p)
p->owner = THIS_MODULE;
- proc_net_fops_create("rt6_stats", S_IRUGO, &rt6_stats_seq_fops);
+ proc_net_fops_create(&init_net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops);
#endif
#ifdef CONFIG_XFRM
xfrm6_init();
@@ -2585,8 +2586,8 @@ void ip6_route_cleanup(void)
fib6_rules_cleanup();
#endif
#ifdef CONFIG_PROC_FS
- proc_net_remove("ipv6_route");
- proc_net_remove("rt6_stats");
+ proc_net_remove(&init_net, "ipv6_route");
+ proc_net_remove(&init_net, "rt6_stats");
#endif
#ifdef CONFIG_XFRM
xfrm6_fini();
diff --git a/net/ipx/ipx_proc.c b/net/ipx/ipx_proc.c
index 4226e71..d483a00 100644
--- a/net/ipx/ipx_proc.c
+++ b/net/ipx/ipx_proc.c
@@ -9,6 +9,7 @@
#include <linux/proc_fs.h>
#include <linux/spinlock.h>
#include <linux/seq_file.h>
+#include <net/net_namespace.h>
#include <net/tcp_states.h>
#include <net/ipx.h>
@@ -353,7 +354,7 @@ int __init ipx_proc_init(void)
struct proc_dir_entry *p;
int rc = -ENOMEM;
- ipx_proc_dir = proc_mkdir("ipx", proc_net);
+ ipx_proc_dir = proc_mkdir("ipx", init_net.proc_net);
if (!ipx_proc_dir)
goto out;
@@ -381,7 +382,7 @@ out_socket:
out_route:
remove_proc_entry("interface", ipx_proc_dir);
out_interface:
- remove_proc_entry("ipx", proc_net);
+ remove_proc_entry("ipx", init_net.proc_net);
goto out;
}
@@ -390,7 +391,7 @@ void __exit ipx_proc_exit(void)
remove_proc_entry("interface", ipx_proc_dir);
remove_proc_entry("route", ipx_proc_dir);
remove_proc_entry("socket", ipx_proc_dir);
- remove_proc_entry("ipx", proc_net);
+ remove_proc_entry("ipx", init_net.proc_net);
}
#else /* CONFIG_PROC_FS */
diff --git a/net/irda/irproc.c b/net/irda/irproc.c
index 181cb51..cae24fb 100644
--- a/net/irda/irproc.c
+++ b/net/irda/irproc.c
@@ -28,6 +28,7 @@
#include <linux/seq_file.h>
#include <linux/module.h>
#include <linux/init.h>
+#include <net/net_namespace.h>
#include <net/irda/irda.h>
#include <net/irda/irlap.h>
@@ -66,7 +67,7 @@ void __init irda_proc_register(void)
int i;
struct proc_dir_entry *d;
- proc_irda = proc_mkdir("irda", proc_net);
+ proc_irda = proc_mkdir("irda", init_net.proc_net);
if (proc_irda == NULL)
return;
proc_irda->owner = THIS_MODULE;
@@ -92,7 +93,7 @@ void irda_proc_unregister(void)
for (i=0; i<ARRAY_SIZE(irda_dirs); i++)
remove_proc_entry(irda_dirs[i].name, proc_irda);
- remove_proc_entry("irda", proc_net);
+ remove_proc_entry("irda", init_net.proc_net);
proc_irda = NULL;
}
}
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 17b2a69..c1a9583 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -26,6 +26,7 @@
#include <linux/in6.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
+#include <net/net_namespace.h>
#include <net/xfrm.h>
#include <linux/audit.h>
@@ -3777,7 +3778,7 @@ static struct xfrm_mgr pfkeyv2_mgr =
static void __exit ipsec_pfkey_exit(void)
{
xfrm_unregister_km(&pfkeyv2_mgr);
- remove_proc_entry("net/pfkey", NULL);
+ remove_proc_entry("pfkey", init_net.proc_net);
sock_unregister(PF_KEY);
proto_unregister(&key_proto);
}
@@ -3794,7 +3795,7 @@ static int __init ipsec_pfkey_init(void)
goto out_unregister_key_proto;
#ifdef CONFIG_PROC_FS
err = -ENOMEM;
- if (create_proc_read_entry("net/pfkey", 0, NULL, pfkey_read_proc, NULL) == NULL)
+ if (create_proc_read_entry("pfkey", 0, init_net.proc_net, pfkey_read_proc, NULL) == NULL)
goto out_sock_unregister;
#endif
err = xfrm_register_km(&pfkeyv2_mgr);
diff --git a/net/llc/llc_proc.c b/net/llc/llc_proc.c
index 49be6c9..4865d82 100644
--- a/net/llc/llc_proc.c
+++ b/net/llc/llc_proc.c
@@ -17,6 +17,7 @@
#include <linux/proc_fs.h>
#include <linux/errno.h>
#include <linux/seq_file.h>
+#include <net/net_namespace.h>
#include <net/sock.h>
#include <net/llc.h>
#include <net/llc_c_ac.h>
@@ -231,7 +232,7 @@ int __init llc_proc_init(void)
int rc = -ENOMEM;
struct proc_dir_entry *p;
- llc_proc_dir = proc_mkdir("llc", proc_net);
+ llc_proc_dir = proc_mkdir("llc", init_net.proc_net);
if (!llc_proc_dir)
goto out;
llc_proc_dir->owner = THIS_MODULE;
@@ -254,7 +255,7 @@ out:
out_core:
remove_proc_entry("socket", llc_proc_dir);
out_socket:
- remove_proc_entry("llc", proc_net);
+ remove_proc_entry("llc", init_net.proc_net);
goto out;
}
@@ -262,5 +263,5 @@ void llc_proc_exit(void)
{
remove_proc_entry("socket", llc_proc_dir);
remove_proc_entry("core", llc_proc_dir);
- remove_proc_entry("llc", proc_net);
+ remove_proc_entry("llc", init_net.proc_net);
}
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 381a77c..a523fa4 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -19,6 +19,7 @@
#include <linux/inetdevice.h>
#include <linux/proc_fs.h>
#include <linux/mutex.h>
+#include <net/net_namespace.h>
#include <net/sock.h>
#include "nf_internals.h"
@@ -293,7 +294,7 @@ void __init netfilter_init(void)
}
#ifdef CONFIG_PROC_FS
- proc_net_netfilter = proc_mkdir("netfilter", proc_net);
+ proc_net_netfilter = proc_mkdir("netfilter", init_net.proc_net);
if (!proc_net_netfilter)
panic("cannot create netfilter proc entry");
#endif
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index 3ac64e2..8a3e3af 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -20,6 +20,7 @@
#include <linux/percpu.h>
#include <linux/kernel.h>
#include <linux/jhash.h>
+#include <net/net_namespace.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_core.h>
@@ -505,7 +506,7 @@ static int __init exp_proc_init(void)
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc;
- proc = proc_net_fops_create("nf_conntrack_expect", 0440, &exp_file_ops);
+ proc = proc_net_fops_create(&init_net, "nf_conntrack_expect", 0440, &exp_file_ops);
if (!proc)
return -ENOMEM;
#endif /* CONFIG_PROC_FS */
@@ -515,7 +516,7 @@ static int __init exp_proc_init(void)
static void exp_proc_remove(void)
{
#ifdef CONFIG_PROC_FS
- proc_net_remove("nf_conntrack_expect");
+ proc_net_remove(&init_net, "nf_conntrack_expect");
#endif /* CONFIG_PROC_FS */
}
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index a4ce5e8..2a19c5f 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -14,6 +14,7 @@
#include <linux/seq_file.h>
#include <linux/percpu.h>
#include <linux/netdevice.h>
+#include <net/net_namespace.h>
#ifdef CONFIG_SYSCTL
#include <linux/sysctl.h>
#endif
@@ -420,10 +421,10 @@ static int __init nf_conntrack_standalone_init(void)
return ret;
#ifdef CONFIG_PROC_FS
- proc = proc_net_fops_create("nf_conntrack", 0440, &ct_file_ops);
+ proc = proc_net_fops_create(&init_net, "nf_conntrack", 0440, &ct_file_ops);
if (!proc) goto cleanup_init;
- proc_stat = create_proc_entry("nf_conntrack", S_IRUGO, proc_net_stat);
+ proc_stat = create_proc_entry("nf_conntrack", S_IRUGO, init_net.proc_net_stat);
if (!proc_stat)
goto cleanup_proc;
@@ -444,9 +445,9 @@ static int __init nf_conntrack_standalone_init(void)
cleanup_proc_stat:
#endif
#ifdef CONFIG_PROC_FS
- remove_proc_entry("nf_conntrack", proc_net_stat);
+ remove_proc_entry("nf_conntrack", init_net. proc_net_stat);
cleanup_proc:
- proc_net_remove("nf_conntrack");
+ proc_net_remove(&init_net, "nf_conntrack");
cleanup_init:
#endif /* CNFIG_PROC_FS */
nf_conntrack_cleanup();
@@ -459,8 +460,8 @@ static void __exit nf_conntrack_standalone_fini(void)
unregister_sysctl_table(nf_ct_sysctl_header);
#endif
#ifdef CONFIG_PROC_FS
- remove_proc_entry("nf_conntrack", proc_net_stat);
- proc_net_remove("nf_conntrack");
+ remove_proc_entry("nf_conntrack", init_net.proc_net_stat);
+ proc_net_remove(&init_net, "nf_conntrack");
#endif /* CNFIG_PROC_FS */
nf_conntrack_cleanup();
}
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index cc2baa6..d9a3bde 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -22,6 +22,7 @@
#include <linux/vmalloc.h>
#include <linux/mutex.h>
#include <linux/mm.h>
+#include <net/net_namespace.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_arp.h>
@@ -795,7 +796,7 @@ int xt_proto_init(int af)
#ifdef CONFIG_PROC_FS
strlcpy(buf, xt_prefix[af], sizeof(buf));
strlcat(buf, FORMAT_TABLES, sizeof(buf));
- proc = proc_net_fops_create(buf, 0440, &xt_file_ops);
+ proc = proc_net_fops_create(&init_net, buf, 0440, &xt_file_ops);
if (!proc)
goto out;
proc->data = (void *) ((unsigned long) af | (TABLE << 16));
@@ -803,14 +804,14 @@ int xt_proto_init(int af)
strlcpy(buf, xt_prefix[af], sizeof(buf));
strlcat(buf, FORMAT_MATCHES, sizeof(buf));
- proc = proc_net_fops_create(buf, 0440, &xt_file_ops);
+ proc = proc_net_fops_create(&init_net, buf, 0440, &xt_file_ops);
if (!proc)
goto out_remove_tables;
proc->data = (void *) ((unsigned long) af | (MATCH << 16));
strlcpy(buf, xt_prefix[af], sizeof(buf));
strlcat(buf, FORMAT_TARGETS, sizeof(buf));
- proc = proc_net_fops_create(buf, 0440, &xt_file_ops);
+ proc = proc_net_fops_create(&init_net, buf, 0440, &xt_file_ops);
if (!proc)
goto out_remove_matches;
proc->data = (void *) ((unsigned long) af | (TARGET << 16));
@@ -822,12 +823,12 @@ int xt_proto_init(int af)
out_remove_matches:
strlcpy(buf, xt_prefix[af], sizeof(buf));
strlcat(buf, FORMAT_MATCHES, sizeof(buf));
- proc_net_remove(buf);
+ proc_net_remove(&init_net, buf);
out_remove_tables:
strlcpy(buf, xt_prefix[af], sizeof(buf));
strlcat(buf, FORMAT_TABLES, sizeof(buf));
- proc_net_remove(buf);
+ proc_net_remove(&init_net, buf);
out:
return -1;
#endif
@@ -841,15 +842,15 @@ void xt_proto_fini(int af)
strlcpy(buf, xt_prefix[af], sizeof(buf));
strlcat(buf, FORMAT_TABLES, sizeof(buf));
- proc_net_remove(buf);
+ proc_net_remove(&init_net, buf);
strlcpy(buf, xt_prefix[af], sizeof(buf));
strlcat(buf, FORMAT_TARGETS, sizeof(buf));
- proc_net_remove(buf);
+ proc_net_remove(&init_net, buf);
strlcpy(buf, xt_prefix[af], sizeof(buf));
strlcat(buf, FORMAT_MATCHES, sizeof(buf));
- proc_net_remove(buf);
+ proc_net_remove(&init_net, buf);
#endif /*CONFIG_PROC_FS*/
}
EXPORT_SYMBOL_GPL(xt_proto_fini);
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index bd45f9d..1910367 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -21,6 +21,7 @@
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
+#include <net/net_namespace.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_ipv4/ip_tables.h>
@@ -743,13 +744,13 @@ static int __init xt_hashlimit_init(void)
printk(KERN_ERR "xt_hashlimit: unable to create slab cache\n");
goto err2;
}
- hashlimit_procdir4 = proc_mkdir("ipt_hashlimit", proc_net);
+ hashlimit_procdir4 = proc_mkdir("ipt_hashlimit", init_net.proc_net);
if (!hashlimit_procdir4) {
printk(KERN_ERR "xt_hashlimit: unable to create proc dir "
"entry\n");
goto err3;
}
- hashlimit_procdir6 = proc_mkdir("ip6t_hashlimit", proc_net);
+ hashlimit_procdir6 = proc_mkdir("ip6t_hashlimit", init_net.proc_net);
if (!hashlimit_procdir6) {
printk(KERN_ERR "xt_hashlimit: unable to create proc dir "
"entry\n");
@@ -757,7 +758,7 @@ static int __init xt_hashlimit_init(void)
}
return 0;
err4:
- remove_proc_entry("ipt_hashlimit", proc_net);
+ remove_proc_entry("ipt_hashlimit", init_net.proc_net);
err3:
kmem_cache_destroy(hashlimit_cachep);
err2:
@@ -769,8 +770,8 @@ err1:
static void __exit xt_hashlimit_fini(void)
{
- remove_proc_entry("ipt_hashlimit", proc_net);
- remove_proc_entry("ip6t_hashlimit", proc_net);
+ remove_proc_entry("ipt_hashlimit", init_net.proc_net);
+ remove_proc_entry("ip6t_hashlimit", init_net.proc_net);
kmem_cache_destroy(hashlimit_cachep);
xt_unregister_matches(xt_hashlimit, ARRAY_SIZE(xt_hashlimit));
}
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index a78d962..3982f13 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -57,6 +57,7 @@
#include <linux/selinux.h>
#include <linux/mutex.h>
+#include <net/net_namespace.h>
#include <net/sock.h>
#include <net/scm.h>
#include <net/netlink.h>
@@ -1927,7 +1928,7 @@ static int __init netlink_proto_init(void)
sock_register(&netlink_family_ops);
#ifdef CONFIG_PROC_FS
- proc_net_fops_create("netlink", 0, &netlink_seq_fops);
+ proc_net_fops_create(&init_net, "netlink", 0, &netlink_seq_fops);
#endif
/* The netlink device handler may be needed early. */
rtnetlink_init();
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index dc92732..15c8a92 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -27,6 +27,7 @@
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/skbuff.h>
+#include <net/net_namespace.h>
#include <net/sock.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -1447,9 +1448,9 @@ static int __init nr_proto_init(void)
nr_loopback_init();
- proc_net_fops_create("nr", S_IRUGO, &nr_info_fops);
- proc_net_fops_create("nr_neigh", S_IRUGO, &nr_neigh_fops);
- proc_net_fops_create("nr_nodes", S_IRUGO, &nr_nodes_fops);
+ proc_net_fops_create(&init_net, "nr", S_IRUGO, &nr_info_fops);
+ proc_net_fops_create(&init_net, "nr_neigh", S_IRUGO, &nr_neigh_fops);
+ proc_net_fops_create(&init_net, "nr_nodes", S_IRUGO, &nr_nodes_fops);
out:
return rc;
fail:
@@ -1477,9 +1478,9 @@ static void __exit nr_exit(void)
{
int i;
- proc_net_remove("nr");
- proc_net_remove("nr_neigh");
- proc_net_remove("nr_nodes");
+ proc_net_remove(&init_net, "nr");
+ proc_net_remove(&init_net, "nr_neigh");
+ proc_net_remove(&init_net, "nr_nodes");
nr_loopback_clear();
nr_rt_free();
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 1322d62..1eecbd7 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -61,6 +61,7 @@
#include <linux/wireless.h>
#include <linux/kernel.h>
#include <linux/kmod.h>
+#include <net/net_namespace.h>
#include <net/ip.h>
#include <net/protocol.h>
#include <linux/skbuff.h>
@@ -1952,7 +1953,7 @@ static const struct file_operations packet_seq_fops = {
static void __exit packet_exit(void)
{
- proc_net_remove("packet");
+ proc_net_remove(&init_net, "packet");
unregister_netdevice_notifier(&packet_netdev_notifier);
sock_unregister(PF_PACKET);
proto_unregister(&packet_proto);
@@ -1967,7 +1968,7 @@ static int __init packet_init(void)
sock_register(&packet_family_ops);
register_netdevice_notifier(&packet_netdev_notifier);
- proc_net_fops_create("packet", 0, &packet_seq_fops);
+ proc_net_fops_create(&init_net, "packet", 0, &packet_seq_fops);
out:
return rc;
}
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index 976c3cc..48319f7 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -26,6 +26,7 @@
#include <linux/sockios.h>
#include <linux/net.h>
#include <linux/stat.h>
+#include <net/net_namespace.h>
#include <net/ax25.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
@@ -1576,10 +1577,10 @@ static int __init rose_proto_init(void)
rose_add_loopback_neigh();
- proc_net_fops_create("rose", S_IRUGO, &rose_info_fops);
- proc_net_fops_create("rose_neigh", S_IRUGO, &rose_neigh_fops);
- proc_net_fops_create("rose_nodes", S_IRUGO, &rose_nodes_fops);
- proc_net_fops_create("rose_routes", S_IRUGO, &rose_routes_fops);
+ proc_net_fops_create(&init_net, "rose", S_IRUGO, &rose_info_fops);
+ proc_net_fops_create(&init_net, "rose_neigh", S_IRUGO, &rose_neigh_fops);
+ proc_net_fops_create(&init_net, "rose_nodes", S_IRUGO, &rose_nodes_fops);
+ proc_net_fops_create(&init_net, "rose_routes", S_IRUGO, &rose_routes_fops);
out:
return rc;
fail:
@@ -1606,10 +1607,10 @@ static void __exit rose_exit(void)
{
int i;
- proc_net_remove("rose");
- proc_net_remove("rose_neigh");
- proc_net_remove("rose_nodes");
- proc_net_remove("rose_routes");
+ proc_net_remove(&init_net, "rose");
+ proc_net_remove(&init_net, "rose_neigh");
+ proc_net_remove(&init_net, "rose_nodes");
+ proc_net_remove(&init_net, "rose_routes");
rose_loopback_clear();
rose_rt_free();
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c
index c58fa0d..122d55d 100644
--- a/net/rxrpc/af_rxrpc.c
+++ b/net/rxrpc/af_rxrpc.c
@@ -14,6 +14,7 @@
#include <linux/skbuff.h>
#include <linux/poll.h>
#include <linux/proc_fs.h>
+#include <net/net_namespace.h>
#include <net/sock.h>
#include <net/af_rxrpc.h>
#include "ar-internal.h"
@@ -829,8 +830,8 @@ static int __init af_rxrpc_init(void)
}
#ifdef CONFIG_PROC_FS
- proc_net_fops_create("rxrpc_calls", 0, &rxrpc_call_seq_fops);
- proc_net_fops_create("rxrpc_conns", 0, &rxrpc_connection_seq_fops);
+ proc_net_fops_create(&init_net, "rxrpc_calls", 0, &rxrpc_call_seq_fops);
+ proc_net_fops_create(&init_net, "rxrpc_conns", 0, &rxrpc_connection_seq_fops);
#endif
return 0;
@@ -868,8 +869,8 @@ static void __exit af_rxrpc_exit(void)
_debug("flush scheduled work");
flush_workqueue(rxrpc_workqueue);
- proc_net_remove("rxrpc_conns");
- proc_net_remove("rxrpc_calls");
+ proc_net_remove(&init_net, "rxrpc_conns");
+ proc_net_remove(&init_net, "rxrpc_calls");
destroy_workqueue(rxrpc_workqueue);
kmem_cache_destroy(rxrpc_call_jar);
_leave("");
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index dee0d5f..efc383c 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -28,6 +28,7 @@
#include <linux/list.h>
#include <linux/hrtimer.h>
+#include <net/net_namespace.h>
#include <net/netlink.h>
#include <net/pkt_sched.h>
@@ -1251,7 +1252,7 @@ static int __init pktsched_init(void)
{
register_qdisc(&pfifo_qdisc_ops);
register_qdisc(&bfifo_qdisc_ops);
- proc_net_fops_create("psched", 0, &psched_fops);
+ proc_net_fops_create(&init_net, "psched", 0, &psched_fops);
rtnl_register(PF_UNSPEC, RTM_NEWQDISC, tc_modify_qdisc, NULL);
rtnl_register(PF_UNSPEC, RTM_DELQDISC, tc_get_qdisc, NULL);
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index a746ebf..a015454 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -52,6 +52,7 @@
#include <linux/inetdevice.h>
#include <linux/seq_file.h>
#include <linux/bootmem.h>
+#include <net/net_namespace.h>
#include <net/protocol.h>
#include <net/ip.h>
#include <net/ipv6.h>
@@ -98,7 +99,7 @@ static __init int sctp_proc_init(void)
{
if (!proc_net_sctp) {
struct proc_dir_entry *ent;
- ent = proc_mkdir("net/sctp", NULL);
+ ent = proc_mkdir("sctp", init_net.proc_net);
if (ent) {
ent->owner = THIS_MODULE;
proc_net_sctp = ent;
@@ -131,7 +132,7 @@ static void sctp_proc_exit(void)
if (proc_net_sctp) {
proc_net_sctp = NULL;
- remove_proc_entry("net/sctp", NULL);
+ remove_proc_entry("sctp", init_net.proc_net);
}
}
diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c
index 74ba7d4..4d4f373 100644
--- a/net/sunrpc/stats.c
+++ b/net/sunrpc/stats.c
@@ -21,6 +21,7 @@
#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/svcsock.h>
#include <linux/sunrpc/metrics.h>
+#include <net/net_namespace.h>
#define RPCDBG_FACILITY RPCDBG_MISC
@@ -265,7 +266,7 @@ rpc_proc_init(void)
dprintk("RPC: registering /proc/net/rpc\n");
if (!proc_net_rpc) {
struct proc_dir_entry *ent;
- ent = proc_mkdir("rpc", proc_net);
+ ent = proc_mkdir("rpc", init_net.proc_net);
if (ent) {
ent->owner = THIS_MODULE;
proc_net_rpc = ent;
@@ -279,7 +280,7 @@ rpc_proc_exit(void)
dprintk("RPC: unregistering /proc/net/rpc\n");
if (proc_net_rpc) {
proc_net_rpc = NULL;
- remove_proc_entry("net/rpc", NULL);
+ remove_proc_entry("rpc", init_net.proc_net);
}
}
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index a05c342..2386090 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -103,6 +103,7 @@
#include <asm/uaccess.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
+#include <net/net_namespace.h>
#include <net/sock.h>
#include <net/tcp_states.h>
#include <net/af_unix.h>
@@ -2135,7 +2136,7 @@ static int __init af_unix_init(void)
sock_register(&unix_family_ops);
#ifdef CONFIG_PROC_FS
- proc_net_fops_create("unix", 0, &unix_seq_fops);
+ proc_net_fops_create(&init_net, "unix", 0, &unix_seq_fops);
#endif
unix_sysctl_register();
out:
@@ -2146,7 +2147,7 @@ static void __exit af_unix_exit(void)
{
sock_unregister(PF_UNIX);
unix_sysctl_unregister();
- proc_net_remove("unix");
+ proc_net_remove(&init_net, "unix");
proto_unregister(&unix_proto);
}
diff --git a/net/wanrouter/wanproc.c b/net/wanrouter/wanproc.c
index 236e7ea..f2e54c3 100644
--- a/net/wanrouter/wanproc.c
+++ b/net/wanrouter/wanproc.c
@@ -29,6 +29,7 @@
#include <linux/seq_file.h>
#include <linux/smp_lock.h>
+#include <net/net_namespace.h>
#include <asm/io.h>
#define PROC_STATS_FORMAT "%30s: %12lu\n"
@@ -287,7 +288,7 @@ static const struct file_operations wandev_fops = {
int __init wanrouter_proc_init(void)
{
struct proc_dir_entry *p;
- proc_router = proc_mkdir(ROUTER_NAME, proc_net);
+ proc_router = proc_mkdir(ROUTER_NAME, init_net.proc_net);
if (!proc_router)
goto fail;
@@ -303,7 +304,7 @@ int __init wanrouter_proc_init(void)
fail_stat:
remove_proc_entry("config", proc_router);
fail_config:
- remove_proc_entry(ROUTER_NAME, proc_net);
+ remove_proc_entry(ROUTER_NAME, init_net.proc_net);
fail:
return -ENOMEM;
}
@@ -316,7 +317,7 @@ void wanrouter_proc_cleanup(void)
{
remove_proc_entry("config", proc_router);
remove_proc_entry("status", proc_router);
- remove_proc_entry(ROUTER_NAME, proc_net);
+ remove_proc_entry(ROUTER_NAME, init_net.proc_net);
}
/*
diff --git a/net/wireless/wext.c b/net/wireless/wext.c
index debf519..b8069af 100644
--- a/net/wireless/wext.c
+++ b/net/wireless/wext.c
@@ -93,6 +93,7 @@
#include <linux/if_arp.h> /* ARPHRD_ETHER */
#include <linux/etherdevice.h> /* compare_ether_addr */
#include <linux/interrupt.h>
+#include <net/net_namespace.h>
#include <linux/wireless.h> /* Pretty obvious */
#include <net/iw_handler.h> /* New driver API */
@@ -686,7 +687,7 @@ static const struct file_operations wireless_seq_fops = {
int __init wext_proc_init(void)
{
/* Create /proc/net/wireless entry */
- if (!proc_net_fops_create("wireless", S_IRUGO, &wireless_seq_fops))
+ if (!proc_net_fops_create(&init_net, "wireless", S_IRUGO, &wireless_seq_fops))
return -ENOMEM;
return 0;
diff --git a/net/x25/x25_proc.c b/net/x25/x25_proc.c
index 7405b9c..7d55e50 100644
--- a/net/x25/x25_proc.c
+++ b/net/x25/x25_proc.c
@@ -20,6 +20,7 @@
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <net/net_namespace.h>
#include <net/sock.h>
#include <net/x25.h>
@@ -301,7 +302,7 @@ int __init x25_proc_init(void)
struct proc_dir_entry *p;
int rc = -ENOMEM;
- x25_proc_dir = proc_mkdir("x25", proc_net);
+ x25_proc_dir = proc_mkdir("x25", init_net.proc_net);
if (!x25_proc_dir)
goto out;
@@ -328,7 +329,7 @@ out_forward:
out_socket:
remove_proc_entry("route", x25_proc_dir);
out_route:
- remove_proc_entry("x25", proc_net);
+ remove_proc_entry("x25", init_net.proc_net);
goto out;
}
@@ -337,7 +338,7 @@ void __exit x25_proc_exit(void)
remove_proc_entry("forward", x25_proc_dir);
remove_proc_entry("route", x25_proc_dir);
remove_proc_entry("socket", x25_proc_dir);
- remove_proc_entry("x25", proc_net);
+ remove_proc_entry("x25", init_net.proc_net);
}
#else /* CONFIG_PROC_FS */
--
1.5.3.rc6.17.g1911
_______________________________________________
Containers mailing list
Containers@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/containers
|
|
|
[PATCH 06/16] net: Add a network namespace parameter to struct sock [message #19973 is a reply to message #19971] |
Sat, 08 September 2007 21:21 |
ebiederm
Messages: 1354 Registered: February 2006
|
Senior Member |
|
|
Sockets need to get a reference to their network namespace,
or possibly a simple hold if someone registers on the network
namespace notifier and will free the sockets when the namespace
is going to be destroyed.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
include/net/inet_timewait_sock.h | 1 +
include/net/sock.h | 3 +++
2 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
index 47d52b2..abaff05 100644
--- a/include/net/inet_timewait_sock.h
+++ b/include/net/inet_timewait_sock.h
@@ -115,6 +115,7 @@ struct inet_timewait_sock {
#define tw_refcnt __tw_common.skc_refcnt
#define tw_hash __tw_common.skc_hash
#define tw_prot __tw_common.skc_prot
+#define tw_net __tw_common.skc_net
volatile unsigned char tw_substate;
/* 3 bits hole, try to pack */
unsigned char tw_rcv_wscale;
diff --git a/include/net/sock.h b/include/net/sock.h
index 802c670..253df3f 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -106,6 +106,7 @@ struct proto;
* @skc_refcnt: reference count
* @skc_hash: hash value used with various protocol lookup tables
* @skc_prot: protocol handlers inside a network family
+ * @skc_net: reference to the network namespace of this socket
*
* This is the minimal network layer representation of sockets, the header
* for struct sock and struct inet_timewait_sock.
@@ -120,6 +121,7 @@ struct sock_common {
atomic_t skc_refcnt;
unsigned int skc_hash;
struct proto *skc_prot;
+ struct net *skc_net;
};
/**
@@ -196,6 +198,7 @@ struct sock {
#define sk_refcnt __sk_common.skc_refcnt
#define sk_hash __sk_common.skc_hash
#define sk_prot __sk_common.skc_prot
+#define sk_net __sk_common.skc_net
unsigned char sk_shutdown : 2,
sk_no_check : 2,
sk_userlocks : 4;
--
1.5.3.rc6.17.g1911
_______________________________________________
Containers mailing list
Containers@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/containers
|
|
|
[PATCH 08/16] net: Make socket creation namespace safe. [message #19974 is a reply to message #19972] |
Sat, 08 September 2007 21:23 |
ebiederm
Messages: 1354 Registered: February 2006
|
Senior Member |
|
|
This patch passes in the namespace a new socket should be created in
and has the socket code do the appropriate reference counting. By
virtue of this all socket create methods are touched. In addition
the socket create methods are modified so that they will fail if
you attempt to create a socket in a non-default network namespace.
Failing if we attempt to create a socket outside of the default
network namespace ensures that as we incrementally make the network stack
network namespace aware we will not export functionality that someone
has not audited and made certain is network namespace safe.
Allowing us to partially enable network namespaces before all of the
exotic protocols are supported.
Any protocol layers I have missed will fail to compile because I now
pass an extra parameter into the socket creation code.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
drivers/net/pppoe.c | 4 ++--
drivers/net/pppol2tp.c | 4 ++--
drivers/net/pppox.c | 7 +++++--
include/linux/if_pppox.h | 2 +-
include/linux/net.h | 3 ++-
include/net/llc_conn.h | 2 +-
include/net/sock.h | 4 +++-
net/appletalk/ddp.c | 7 +++++--
net/atm/common.c | 4 ++--
net/atm/common.h | 2 +-
net/atm/pvc.c | 7 +++++--
net/atm/svc.c | 11 +++++++----
net/ax25/af_ax25.c | 9 ++++++---
net/bluetooth/af_bluetooth.c | 7 +++++--
net/bluetooth/bnep/sock.c | 4 ++--
net/bluetooth/cmtp/sock.c | 4 ++--
net/bluetooth/hci_sock.c | 4 ++--
net/bluetooth/hidp/sock.c | 4 ++--
net/bluetooth/l2cap.c | 10 +++++-----
net/bluetooth/rfcomm/sock.c | 10 +++++-----
net/bluetooth/sco.c | 10 +++++-----
net/core/sock.c | 6 ++++--
net/decnet/af_decnet.c | 13 ++++++++-----
net/econet/af_econet.c | 7 +++++--
net/ipv4/af_inet.c | 7 +++++--
net/ipv6/af_inet6.c | 7 +++++--
net/ipx/af_ipx.c | 7 +++++--
net/irda/af_irda.c | 11 +++++++----
net/key/af_key.c | 7 +++++--
net/llc/af_llc.c | 7 +++++--
net/llc/llc_conn.c | 6 +++---
net/netlink/af_netlink.c | 15 +++++++++------
net/netrom/af_netrom.c | 9 ++++++---
net/packet/af_packet.c | 7 +++++--
net/rose/af_rose.c | 9 ++++++---
net/rxrpc/af_rxrpc.c | 7 +++++--
net/sctp/ipv6.c | 2 +-
net/sctp/protocol.c | 2 +-
net/socket.c | 9 +++++----
net/tipc/socket.c | 9 ++++++---
net/unix/af_unix.c | 13 ++++++++-----
net/x25/af_x25.c | 13 ++++++++-----
42 files changed, 182 insertions(+), 110 deletions(-)
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index a9b6971..f8bf5fc 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -477,12 +477,12 @@ static struct proto pppoe_sk_proto = {
* Initialize a new struct sock.
*
**********************************************************************/
-static int pppoe_create(struct socket *sock)
+static int pppoe_create(struct net *net, struct socket *sock)
{
int error = -ENOMEM;
struct sock *sk;
- sk = sk_alloc(PF_PPPOX, GFP_KERNEL, &pppoe_sk_proto, 1);
+ sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pppoe_sk_proto, 1);
if (!sk)
goto out;
diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c
index c12e0a8..07d7f5b 100644
--- a/drivers/net/pppol2tp.c
+++ b/drivers/net/pppol2tp.c
@@ -1423,12 +1423,12 @@ static struct proto pppol2tp_sk_proto = {
/* socket() handler. Initialize a new struct sock.
*/
-static int pppol2tp_create(struct socket *sock)
+static int pppol2tp_create(struct net *net, struct socket *sock)
{
int error = -ENOMEM;
struct sock *sk;
- sk = sk_alloc(PF_PPPOX, GFP_KERNEL, &pppol2tp_sk_proto, 1);
+ sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pppol2tp_sk_proto, 1);
if (!sk)
goto out;
diff --git a/drivers/net/pppox.c b/drivers/net/pppox.c
index 25c52b5..c6898c1 100644
--- a/drivers/net/pppox.c
+++ b/drivers/net/pppox.c
@@ -104,10 +104,13 @@ int pppox_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
EXPORT_SYMBOL(pppox_ioctl);
-static int pppox_create(struct socket *sock, int protocol)
+static int pppox_create(struct net *net, struct socket *sock, int protocol)
{
int rc = -EPROTOTYPE;
+ if (net != &init_net)
+ return -EAFNOSUPPORT;
+
if (protocol < 0 || protocol > PX_MAX_PROTO)
goto out;
@@ -123,7 +126,7 @@ static int pppox_create(struct socket *sock, int protocol)
!try_module_get(pppox_protos[protocol]->owner))
goto out;
- rc = pppox_protos[protocol]->create(sock);
+ rc = pppox_protos[protocol]->create(net, sock);
module_put(pppox_protos[protocol]->owner);
out:
diff --git a/include/linux/if_pppox.h b/include/linux/if_pppox.h
index 2565254..43cfc9f 100644
--- a/include/linux/if_pppox.h
+++ b/include/linux/if_pppox.h
@@ -172,7 +172,7 @@ static inline struct sock *sk_pppox(struct pppox_sock *po)
struct module;
struct pppox_proto {
- int (*create)(struct socket *sock);
+ int (*create)(struct net *net, struct socket *sock);
int (*ioctl)(struct socket *sock, unsigned int cmd,
unsigned long arg);
struct module *owner;
diff --git a/include/linux/net.h b/include/linux/net.h
index efc4517..c136abc 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -23,6 +23,7 @@
struct poll_table_struct;
struct inode;
+struct net;
#define NPROTO 34 /* should be enough for now.. */
@@ -169,7 +170,7 @@ struct proto_ops {
struct net_proto_family {
int family;
- int (*create)(struct socket *sock, int protocol);
+ int (*create)(struct net *net, struct socket *sock, int protocol);
struct module *owner;
};
diff --git a/include/net/llc_conn.h b/include/net/llc_conn.h
index 00730d2..e2374e3 100644
--- a/include/net/llc_conn.h
+++ b/include/net/llc_conn.h
@@ -93,7 +93,7 @@ static __inline__ char llc_backlog_type(struct sk_buff *skb)
return skb->cb[sizeof(skb->cb) - 1];
}
-extern struct sock *llc_sk_alloc(int family, gfp_t priority,
+extern struct sock *llc_sk_alloc(struct net *net, int family, gfp_t priority,
struct proto *prot);
extern void llc_sk_free(struct sock *sk);
diff --git a/include/net/sock.h b/include/net/sock.h
index 253df3f..898413f 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -56,6 +56,7 @@
#include <asm/atomic.h>
#include <net/dst.h>
#include <net/checksum.h>
+#include <net/net_namespace.h>
/*
* This structure really needs to be cleaned up.
@@ -777,7 +778,7 @@ extern void FASTCALL(release_sock(struct sock *sk));
SINGLE_DEPTH_NESTING)
#define bh_unlock_sock(__sk) spin_unlock(&((__sk)->sk_lock.slock))
-extern struct sock *sk_alloc(int family,
+extern struct sock *sk_alloc(struct net *net, int family,
gfp_t priority,
struct proto *prot, int zero_it);
extern void sk_free(struct sock *sk);
@@ -1006,6 +1007,7 @@ static inline void sock_copy(struct sock *nsk, const struct sock *osk)
#endif
memcpy(nsk, osk, osk->sk_prot->obj_size);
+ get_net(nsk->sk_net);
#ifdef CONFIG_SECURITY_NETWORK
nsk->sk_security = sptr;
security_sk_clone(osk, nsk);
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 594b597..fd1d52f 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -1026,11 +1026,14 @@ static struct proto ddp_proto = {
* Create a socket. Initialise the socket, blank the addresses
* set the state.
*/
-static int atalk_create(struct socket *sock, int protocol)
+static int atalk_create(struct net *net, struct socket *sock, int protocol)
{
struct sock *sk;
int rc = -ESOCKTNOSUPPORT;
+ if (net != &init_net)
+ return -EAFNOSUPPORT;
+
/*
* We permit SOCK_DGRAM and RAW is an extension. It is trivial to do
* and gives you the full ELAP frame. Should be handy for CAP 8)
@@ -1038,7 +1041,7 @@ static int atalk_create(struct socket *sock, int protocol)
if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM)
goto out;
rc = -ENOMEM;
- sk = sk_alloc(PF_APPLETALK, GFP_KERNEL, &ddp_proto, 1);
+ sk = sk_alloc(net, PF_APPLETALK, GFP_KERNEL, &ddp_proto, 1);
if (!sk)
goto out;
rc = 0;
diff --git a/net/atm/common.c b/net/atm/common.c
index 299ec1e..e166d9e 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -125,7 +125,7 @@ static struct proto vcc_proto = {
.obj_size = sizeof(struct atm_vcc),
};
-int vcc_create(struct socket *sock, int protocol, int family)
+int vcc_create(struct net *net, struct socket *sock, int protocol, int family)
{
struct sock *sk;
struct atm_vcc *vcc;
@@ -133,7 +133,7 @@ int vcc_create(struct socket *sock, int protocol, int family)
sock->sk = NULL;
if (sock->type == SOCK_STREAM)
return -EINVAL;
- sk = sk_alloc(family, GFP_KERNEL, &vcc_proto, 1);
+ sk = sk_alloc(net, family, GFP_KERNEL, &vcc_proto, 1);
if (!sk)
return -ENOMEM;
sock_init_data(sock, sk);
diff --git a/net/atm/common.h b/net/atm/common.h
index ad78c9e..16f32c1 100644
--- a/net/atm/common.h
+++ b/net/atm/common.h
@@ -10,7 +10,7 @@
#include <linux/poll.h> /* for poll_table */
-int vcc_create(struct socket *sock, int protocol, int family);
+int vcc_create(struct net *net, struct socket *sock, int protocol, int family);
int vcc_release(struct socket *sock);
int vcc_connect(struct socket *sock, int itf, short vpi, int vci);
int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
diff --git a/net/atm/pvc.c b/net/atm/pvc.c
index 848e6e1..43e8bf5 100644
--- a/net/atm/pvc.c
+++ b/net/atm/pvc.c
@@ -124,10 +124,13 @@ static const struct proto_ops pvc_proto_ops = {
};
-static int pvc_create(struct socket *sock,int protocol)
+static int pvc_create(struct net *net, struct socket *sock,int p
...
|
|
|
|
[PATCH 10/16] net: Make packet reception network namespace safe [message #19976 is a reply to message #19975] |
Sat, 08 September 2007 21:25 |
ebiederm
Messages: 1354 Registered: February 2006
|
Senior Member |
|
|
This patch modifies every packet receive function
registered with dev_add_pack() to drop packets if they
are not from the initial network namespace.
This should ensure that the various network stacks do
not receive packets in a anything but the initial network
namespace until the code has been converted and is ready
for them.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
drivers/block/aoe/aoenet.c | 4 ++++
drivers/net/bonding/bond_3ad.c | 4 ++++
drivers/net/bonding/bond_alb.c | 3 +++
drivers/net/bonding/bond_main.c | 3 +++
drivers/net/hamradio/bpqether.c | 3 +++
drivers/net/pppoe.c | 6 ++++++
drivers/net/wan/hdlc.c | 7 +++++++
drivers/net/wan/lapbether.c | 3 +++
drivers/net/wan/syncppp.c | 6 ++++++
net/8021q/vlan_dev.c | 5 +++++
net/appletalk/aarp.c | 3 +++
net/appletalk/ddp.c | 6 ++++++
net/ax25/ax25_in.c | 5 +++++
net/bridge/br_stp_bpdu.c | 4 ++++
net/decnet/dn_route.c | 3 +++
net/econet/af_econet.c | 3 +++
net/ipv4/arp.c | 3 +++
net/ipv4/ip_input.c | 3 +++
net/ipv4/ipconfig.c | 6 ++++++
net/ipv6/ip6_input.c | 5 +++++
net/ipx/af_ipx.c | 3 +++
net/irda/irlap_frame.c | 3 +++
net/llc/llc_input.c | 4 ++++
net/packet/af_packet.c | 9 +++++++++
net/tipc/eth_media.c | 6 ++++++
net/x25/x25_dev.c | 3 +++
26 files changed, 113 insertions(+), 0 deletions(-)
diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c
index f9ddfda..4dc0fb7 100644
--- a/drivers/block/aoe/aoenet.c
+++ b/drivers/block/aoe/aoenet.c
@@ -8,6 +8,7 @@
#include <linux/blkdev.h>
#include <linux/netdevice.h>
#include <linux/moduleparam.h>
+#include <net/net_namespace.h>
#include <asm/unaligned.h>
#include "aoe.h"
@@ -114,6 +115,9 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt,
struct aoe_hdr *h;
u32 n;
+ if (ifp->nd_net != &init_net)
+ goto exit;
+
skb = skb_share_check(skb, GFP_ATOMIC);
if (skb == NULL)
return 0;
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index f829e4a..94bd739 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -29,6 +29,7 @@
#include <linux/ethtool.h>
#include <linux/if_bonding.h>
#include <linux/pkt_sched.h>
+#include <net/net_namespace.h>
#include "bonding.h"
#include "bond_3ad.h"
@@ -2448,6 +2449,9 @@ int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct pac
struct slave *slave = NULL;
int ret = NET_RX_DROP;
+ if (dev->nd_net != &init_net)
+ goto out;
+
if (!(dev->flags & IFF_MASTER))
goto out;
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 92c3b6f..419a9f8 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -345,6 +345,9 @@ static int rlb_arp_recv(struct sk_buff *skb, struct net_device *bond_dev, struct
struct arp_pkt *arp = (struct arp_pkt *)skb->data;
int res = NET_RX_DROP;
+ if (bond_dev->nd_net != &init_net)
+ goto out;
+
if (!(bond_dev->flags & IFF_MASTER))
goto out;
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 5de648f..e4e5fdc 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -2458,6 +2458,9 @@ static int bond_arp_rcv(struct sk_buff *skb, struct net_device *dev, struct pack
unsigned char *arp_ptr;
u32 sip, tip;
+ if (dev->nd_net != &init_net)
+ goto out;
+
if (!(dev->priv_flags & IFF_BONDING) || !(dev->flags & IFF_MASTER))
goto out;
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index 1699d42..85fb8e7 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -173,6 +173,9 @@ static int bpq_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty
struct ethhdr *eth;
struct bpqdev *bpq;
+ if (dev->nd_net != &init_net)
+ goto drop;
+
if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
return NET_RX_DROP;
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index f8bf5fc..a29ea22 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -386,6 +386,9 @@ static int pppoe_rcv(struct sk_buff *skb,
struct pppoe_hdr *ph;
struct pppox_sock *po;
+ if (dev->nd_net != &init_net)
+ goto drop;
+
if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr)))
goto drop;
@@ -418,6 +421,9 @@ static int pppoe_disc_rcv(struct sk_buff *skb,
struct pppoe_hdr *ph;
struct pppox_sock *po;
+ if (dev->nd_net != &init_net)
+ goto abort;
+
if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr)))
goto abort;
diff --git a/drivers/net/wan/hdlc.c b/drivers/net/wan/hdlc.c
index 65ad2e2..3b57350 100644
--- a/drivers/net/wan/hdlc.c
+++ b/drivers/net/wan/hdlc.c
@@ -36,6 +36,7 @@
#include <linux/rtnetlink.h>
#include <linux/notifier.h>
#include <linux/hdlc.h>
+#include <net/net_namespace.h>
static const char* version = "HDLC support module revision 1.21";
@@ -66,6 +67,12 @@ static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *p, struct net_device *orig_dev)
{
struct hdlc_device_desc *desc = dev_to_desc(dev);
+
+ if (dev->nd_net != &init_net) {
+ kfree_skb(skb);
+ return 0;
+ }
+
if (desc->netif_rx)
return desc->netif_rx(skb);
diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c
index 6c302e9..ca8b3c3 100644
--- a/drivers/net/wan/lapbether.c
+++ b/drivers/net/wan/lapbether.c
@@ -91,6 +91,9 @@ static int lapbeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
int len, err;
struct lapbethdev *lapbeth;
+ if (dev->nd_net != &init_net)
+ goto drop;
+
if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
return NET_RX_DROP;
diff --git a/drivers/net/wan/syncppp.c b/drivers/net/wan/syncppp.c
index 67fc67c..5c71af6 100644
--- a/drivers/net/wan/syncppp.c
+++ b/drivers/net/wan/syncppp.c
@@ -51,6 +51,7 @@
#include <linux/spinlock.h>
#include <linux/rcupdate.h>
+#include <net/net_namespace.h>
#include <net/syncppp.h>
#include <asm/byteorder.h>
@@ -1445,6 +1446,11 @@ static void sppp_print_bytes (u_char *p, u16 len)
static int sppp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *p, struct net_device *orig_dev)
{
+ if (dev->nd_net != &init_net) {
+ kfree_skb(skb);
+ return 0;
+ }
+
if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
return NET_RX_DROP;
sppp_input(dev,skb);
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 328759c..6644e8f 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -122,6 +122,11 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
unsigned short vlan_TCI;
__be16 proto;
+ if (dev->nd_net != &init_net) {
+ kfree_skb(skb);
+ return -1;
+ }
+
if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
return -1;
diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c
index 80b5414..9267f48 100644
--- a/net/appletalk/aarp.c
+++ b/net/appletalk/aarp.c
@@ -713,6 +713,9 @@ static int aarp_rcv(struct sk_buff *skb, struct net_device *dev,
struct atalk_addr sa, *ma, da;
struct atalk_iface *ifa;
+ if (dev->nd_net != &init_net)
+ goto out0;
+
/* We only do Ethernet SNAP AARP. */
if (dev->type != ARPHRD_ETHER)
goto out0;
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index fd1d52f..c1f1367 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -1403,6 +1403,9 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
int origlen;
__u16 len_hops;
+ if (dev->nd_net != &init_net)
+ goto freeit;
+
/* Don't mangle buffer if shared */
if (!(skb = skb_share_check(skb, GFP_ATOMIC)))
goto out;
@@ -1488,6 +1491,9 @@ freeit:
static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt, struct net_device *orig_dev)
{
+ if (dev->nd_net != &init_net)
+ goto freeit;
+
/* Expand any short form frames */
if (skb_mac_header(skb)[2] == 1) {
struct ddpehdr *ddp;
diff --git a/net/ax25/ax25_in.c b/net/ax25/ax25_in.c
index 0ddaff0..3b7d172 100644
--- a/net/ax25/ax25_in.c
+++ b/net/ax25/ax25_in.c
@@ -451,6 +451,11 @@ int ax25_kiss_rcv(struct sk_buff *skb, struct net_device *dev,
skb->sk = NULL; /* Initially we don't know who it's for */
skb->destructor = NULL; /* Who initializes this, dammit?! */
+ if (dev->nd_net != &init_net) {
+ kfree_skb(skb);
+ return 0;
+ }
+
if ((*skb->data & 0x0F) != 0) {
kfree_skb(skb); /* Not a KISS data frame */
return 0;
diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c
index 14f0c88..0edbd2a 100644
--- a/net/bridge/br_stp_bpdu.c
+++ b/net/bridge/br_stp_bpdu.c
@@ -17,6 +17,7 @@
#include <linux/netfilter_bridge.h>
#include <linux/etherdevice.h>
#include <linux/llc.h>
+#include <net/net_namespace.h>
#include <net/llc.h>
#include <net/llc_pdu.h>
#include <asm/unaligned.h>
@@ -141,6 +142,9 @@ int br_stp_rcv(struct sk_buff *skb, struct net_device *dev,
struct net_bridge *br;
const unsigned char *buf;
+ if (dev->nd_net != &init_net)
+ goto err;
+
if (!p)
goto err;
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 4cfea95..580e786 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -584,6 +584,9 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type
struct dn_dev *dn = (struct dn_dev *)dev->dn_ptr;
unsigned char padlen = 0;
+ if (dev->nd_net != &init_net)
+ goto dump_it;
+
if (dn == NULL)
goto dump_it;
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c
index a2429db..7de3006 100644
--- a/net/econet/af_econet.c
+++ b/net/econet/af_econet.c
@@ -1065,6 +1065,9 @@ static int econet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet
struct sock *sk;
struct ec_device *edev = dev->ec_ptr;
+ if (dev->nd_net != &init_net)
+ goto drop;
+
if (skb->pkt_type == PACKET_OTHERHOST)
goto drop;
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 78dd344..bde1297 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -932,6 +932,9 @@ static int arp_rcv(struct sk_buff *skb, struct net_device *dev,
{
struct arphdr *arp;
+ if (dev->nd_net != &init_net)
+ goto freeskb;
+
/* ARP header, plus 2 device addresses, plus 2 IP addresses. */
if (!pskb_may_pull(skb, (sizeof(struct arphdr) +
(2 * dev->addr_len) +
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 9706939..41d8964 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -382,6 +382,9 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
struct iphdr *iph;
u32 len;
+ if (dev->nd_net != &init_net)
+ goto drop;
+
/* When the interface is in promisc. mode, drop all the crap
* that it receives, do not try to analyse it.
*/
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index 5ae4849..08ff623 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -426,6 +426,9 @@ ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
unsigned char *sha, *tha; /* s for "source", t for "target" */
struct ic_device *d;
+ if (dev->nd_net != &init_net)
+ goto drop;
+
if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
return NET_RX_DROP;
@@ -835,6 +838,9 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str
struct ic_device *d;
int len, ext_len;
+ if (dev->nd_net != &init_net)
+ goto drop;
+
/* Perform verifications before taking the lock. */
if (skb->pkt_type == PACKET_OTHERHOST)
goto drop;
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 30a5cb1..7d18cac 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -61,6 +61,11 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
u32 pkt_len;
struct inet6_dev *idev;
+ if (dev->nd_net != &init_net) {
+ kfree_skb(skb);
+ return 0;
+ }
+
if (skb->pkt_type == PACKET_OTHERHOST) {
kfree_skb(skb);
return 0;
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
index ee28bab..f7b4d38 100644
--- a/net/ipx/af_ipx.c
+++ b/net/ipx/af_ipx.c
@@ -1647,6 +1647,9 @@ static int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty
u16 ipx_pktsize;
int rc = 0;
+ if (dev->nd_net != &init_net)
+ goto drop;
+
/* Not ours */
if (skb->pkt_type == PACKET_OTHERHOST)
goto drop;
diff --git a/net/irda/irlap_frame.c b/net/irda/irlap_frame.c
index 25a3444..77ac27e 100644
--- a/net/irda/irlap_frame.c
+++ b/net/irda/irlap_frame.c
@@ -1326,6 +1326,9 @@ int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
int command;
__u8 control;
+ if (dev->nd_net != &init_net)
+ goto out;
+
/* FIXME: should we get our own field? */
self = (struct irlap_cb *) dev->atalk_ptr;
diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c
index 099ed8f..c40c9b2 100644
--- a/net/llc/llc_input.c
+++ b/net/llc/llc_input.c
@@ -12,6 +12,7 @@
* See the GNU General Public License for more details.
*/
#include <linux/netdevice.h>
+#include <net/net_namespace.h>
#include <net/llc.h>
#include <net/llc_pdu.h>
#include <net/llc_sap.h>
@@ -145,6 +146,9 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev,
int (*rcv)(struct sk_buff *, struct net_device *,
struct packet_type *, struct net_device *);
+ if (dev->nd_net != &init_net)
+ goto drop;
+
/*
* When the interface is in promisc. mode, drop all the crap that it
* receives, do not try to analyse it.
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 72ff099..51b0d5c 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -252,6 +252,9 @@ static int packet_rcv_spkt(struct sk_buff *skb, struct net_device *dev, struct
struct sock *sk;
struct sockaddr_pkt *spkt;
+ if (dev->nd_net != &init_net)
+ goto out;
+
/*
* When we registered the protocol we saved the socket in the data
* field for just this event.
@@ -452,6 +455,9 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet
int skb_len = skb->len;
unsigned int snaplen, res;
+ if (dev->nd_net != &init_net)
+ goto drop;
+
if (skb->pkt_type == PACKET_LOOPBACK)
goto drop;
@@ -568,6 +574,9 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
struct sk_buff *copy_skb = NULL;
struct timeval tv;
+ if (dev->nd_net != &init_net)
+ goto drop;
+
if (skb->pkt_type == PACKET_LOOPBACK)
goto drop;
diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c
index 711ca4b..d2ed237 100644
--- a/net/tipc/eth_media.c
+++ b/net/tipc/eth_media.c
@@ -38,6 +38,7 @@
#include <net/tipc/tipc_bearer.h>
#include <net/tipc/tipc_msg.h>
#include <linux/netdevice.h>
+#include <net/net_namespace.h>
#define MAX_ETH_BEARERS 2
#define ETH_LINK_PRIORITY TIPC_DEF_LINK_PRI
@@ -100,6 +101,11 @@ static int recv_msg(struct sk_buff *buf, struct net_device *dev,
struct eth_bearer *eb_ptr = (struct eth_bearer *)pt->af_packet_priv;
u32 size;
+ if (dev->nd_net != &init_net) {
+ kfree_skb(buf);
+ return 0;
+ }
+
if (likely(eb_ptr->bearer)) {
if (likely(buf->pkt_type <= PACKET_BROADCAST)) {
size = msg_size((struct tipc_msg *)buf->data);
diff --git a/net/x25/x25_dev.c b/net/x25/x25_dev.c
index 848a6b6..f0679d2 100644
--- a/net/x25/x25_dev.c
+++ b/net/x25/x25_dev.c
@@ -95,6 +95,9 @@ int x25_lapb_receive_frame(struct sk_buff *skb, struct net_device *dev,
struct sk_buff *nskb;
struct x25_neigh *nb;
+ if (dev->nd_net != &init_net)
+ goto drop;
+
nskb = skb_copy(skb, GFP_ATOMIC);
if (!nskb)
goto drop;
--
1.5.3.rc6.17.g1911
_______________________________________________
Containers mailing list
Containers@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/containers
|
|
|
[PATCH 11/16] net: Make device event notification network namespace safe [message #19977 is a reply to message #19976] |
Sat, 08 September 2007 21:27 |
ebiederm
Messages: 1354 Registered: February 2006
|
Senior Member |
|
|
Every user of the network device notifiers is either a protocol
stack or a pseudo device. If a protocol stack that does not have
support for multiple network namespaces receives an event for a
device that is not in the initial network namespace it quite possibly
can get confused and do the wrong thing.
To avoid problems until all of the protocol stacks are converted
this patch modifies all netdev event handlers to ignore events on
devices that are not in the initial network namespace.
As the rest of the code is made network namespace aware these
checks can be removed.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
arch/ia64/hp/sim/simeth.c | 3 +++
drivers/net/bonding/bond_main.c | 3 +++
drivers/net/hamradio/bpqether.c | 3 +++
drivers/net/pppoe.c | 3 +++
drivers/net/wan/dlci.c | 3 +++
drivers/net/wan/hdlc.c | 3 +++
drivers/net/wan/lapbether.c | 3 +++
net/8021q/vlan.c | 4 ++++
net/appletalk/aarp.c | 3 +++
net/appletalk/ddp.c | 3 +++
net/atm/clip.c | 3 +++
net/atm/mpc.c | 4 ++++
net/ax25/af_ax25.c | 3 +++
net/bridge/br_notify.c | 4 ++++
net/core/dst.c | 4 ++++
net/core/fib_rules.c | 4 ++++
net/core/pktgen.c | 3 +++
net/core/rtnetlink.c | 4 ++++
net/decnet/af_decnet.c | 3 +++
net/econet/af_econet.c | 3 +++
net/ipv4/arp.c | 3 +++
net/ipv4/devinet.c | 3 +++
net/ipv4/fib_frontend.c | 3 +++
net/ipv4/ipmr.c | 7 ++++++-
net/ipv4/netfilter/ip_queue.c | 3 +++
net/ipv4/netfilter/ipt_MASQUERADE.c | 3 +++
net/ipv6/addrconf.c | 3 +++
net/ipv6/ndisc.c | 3 +++
net/ipv6/netfilter/ip6_queue.c | 3 +++
net/ipx/af_ipx.c | 3 +++
net/netfilter/nfnetlink_queue.c | 3 +++
net/netrom/af_netrom.c | 3 +++
net/packet/af_packet.c | 3 +++
net/rose/af_rose.c | 3 +++
net/tipc/eth_media.c | 3 +++
net/x25/af_x25.c | 3 +++
net/xfrm/xfrm_policy.c | 5 +++++
security/selinux/netif.c | 4 ++++
38 files changed, 126 insertions(+), 1 deletions(-)
diff --git a/arch/ia64/hp/sim/simeth.c b/arch/ia64/hp/sim/simeth.c
index f26077a..93d6004 100644
--- a/arch/ia64/hp/sim/simeth.c
+++ b/arch/ia64/hp/sim/simeth.c
@@ -300,6 +300,9 @@ simeth_device_event(struct notifier_block *this,unsigned long event, void *ptr)
return NOTIFY_DONE;
}
+ if (dev->nd_net != &init_net)
+ return NOTIFY_DONE;
+
if ( event != NETDEV_UP && event != NETDEV_DOWN ) return NOTIFY_DONE;
/*
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index e4e5fdc..cf97d8a 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3299,6 +3299,9 @@ static int bond_netdev_event(struct notifier_block *this, unsigned long event, v
{
struct net_device *event_dev = (struct net_device *)ptr;
+ if (event_dev->nd_net != &init_net)
+ return NOTIFY_DONE;
+
dprintk("event_dev: %s, event: %lx\n",
(event_dev ? event_dev->name : "None"),
event);
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index 85fb8e7..df09210 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -563,6 +563,9 @@ static int bpq_device_event(struct notifier_block *this,unsigned long event, voi
{
struct net_device *dev = (struct net_device *)ptr;
+ if (dev->nd_net != &init_net)
+ return NOTIFY_DONE;
+
if (!dev_is_ethdev(dev))
return NOTIFY_DONE;
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index a29ea22..b4ba584 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -301,6 +301,9 @@ static int pppoe_device_event(struct notifier_block *this,
{
struct net_device *dev = (struct net_device *) ptr;
+ if (dev->nd_net != &init_net)
+ return NOTIFY_DONE;
+
/* Only look at sockets that are using this specific device. */
switch (event) {
case NETDEV_CHANGEMTU:
diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c
index 66be20c..61041d5 100644
--- a/drivers/net/wan/dlci.c
+++ b/drivers/net/wan/dlci.c
@@ -513,6 +513,9 @@ static int dlci_dev_event(struct notifier_block *unused,
{
struct net_device *dev = (struct net_device *) ptr;
+ if (dev->nd_net != &init_net)
+ return NOTIFY_DONE;
+
if (event == NETDEV_UNREGISTER) {
struct dlci_local *dlp;
diff --git a/drivers/net/wan/hdlc.c b/drivers/net/wan/hdlc.c
index 3b57350..ee23b91 100644
--- a/drivers/net/wan/hdlc.c
+++ b/drivers/net/wan/hdlc.c
@@ -109,6 +109,9 @@ static int hdlc_device_event(struct notifier_block *this, unsigned long event,
unsigned long flags;
int on;
+ if (dev->nd_net != &init_net)
+ return NOTIFY_DONE;
+
if (dev->get_stats != hdlc_get_stats)
return NOTIFY_DONE; /* not an HDLC device */
diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c
index ca8b3c3..699b934 100644
--- a/drivers/net/wan/lapbether.c
+++ b/drivers/net/wan/lapbether.c
@@ -394,6 +394,9 @@ static int lapbeth_device_event(struct notifier_block *this,
struct lapbethdev *lapbeth;
struct net_device *dev = ptr;
+ if (dev->nd_net != &init_net)
+ return NOTIFY_DONE;
+
if (!dev_is_ethdev(dev))
return NOTIFY_DONE;
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 1583c5e..55f2dbb 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -31,6 +31,7 @@
#include <net/arp.h>
#include <linux/rtnetlink.h>
#include <linux/notifier.h>
+#include <net/net_namespace.h>
#include <linux/if_vlan.h>
#include "vlan.h"
@@ -605,6 +606,9 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
int i, flgs;
struct net_device *vlandev;
+ if (dev->nd_net != &init_net)
+ return NOTIFY_DONE;
+
if (!grp)
goto out;
diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c
index 9267f48..e9a51a6 100644
--- a/net/appletalk/aarp.c
+++ b/net/appletalk/aarp.c
@@ -333,6 +333,9 @@ static int aarp_device_event(struct notifier_block *this, unsigned long event,
struct net_device *dev = ptr;
int ct;
+ if (dev->nd_net != &init_net)
+ return NOTIFY_DONE;
+
if (event == NETDEV_DOWN) {
write_lock_bh(&aarp_lock);
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index c1f1367..36fcdbf 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -649,6 +649,9 @@ static int ddp_device_event(struct notifier_block *this, unsigned long event,
{
struct net_device *dev = ptr;
+ if (dev->nd_net != &init_net)
+ return NOTIFY_DONE;
+
if (event == NETDEV_DOWN)
/* Discard any use of this */
atalk_dev_down(dev);
diff --git a/net/atm/clip.c b/net/atm/clip.c
index 806ea98..741742f 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -612,6 +612,9 @@ static int clip_device_event(struct notifier_block *this, unsigned long event,
{
struct net_device *dev = arg;
+ if (dev->nd_net != &init_net)
+ return NOTIFY_DONE;
+
if (event == NETDEV_UNREGISTER) {
neigh_ifdown(&clip_tbl, dev);
return NOTIFY_DONE;
diff --git a/net/atm/mpc.c b/net/atm/mpc.c
index 7c85aa5..0968430 100644
--- a/net/atm/mpc.c
+++ b/net/atm/mpc.c
@@ -956,6 +956,10 @@ static int mpoa_event_listener(struct notifier_block *mpoa_notifier, unsigned lo
struct lec_priv *priv;
dev = (struct net_device *)dev_ptr;
+
+ if (dev->nd_net != &init_net)
+ return NOTIFY_DONE;
+
if (dev->name == NULL || strncmp(dev->name, "lec", 3))
return NOTIFY_DONE; /* we are only interested in lec:s */
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index def6c42..8d13a8b 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -104,6 +104,9 @@ static int ax25_device_event(struct notifier_block *this, unsigned long event,
{
struct net_device *dev = (struct net_device *)ptr;
+ if (dev->nd_net != &init_net)
+ return NOTIFY_DONE;
+
/* Reject non AX.25 devices */
if (dev->type != ARPHRD_AX25)
return NOTIFY_DONE;
diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c
index c8451d3..07ac3ae 100644
--- a/net/bridge/br_notify.c
+++ b/net/bridge/br_notify.c
@@ -15,6 +15,7 @@
#include <linux/kernel.h>
#include <linux/rtnetlink.h>
+#include <net/net_namespace.h>
#include "br_private.h"
@@ -36,6 +37,9 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
struct net_bridge_port *p = dev->br_port;
struct net_bridge *br;
+ if (dev->nd_net != &init_net)
+ return NOTIFY_DONE;
+
/* not a port of a bridge */
if (p == NULL)
return NOTIFY_DONE;
diff --git a/net/core/dst.c b/net/core/dst.c
index c6a0587..32267a1 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -15,6 +15,7 @@
#include <linux/skbuff.h>
#include <linux/string.h>
#include <linux/types.h>
+#include <net/net_namespace.h>
#include <net/dst.h>
@@ -252,6 +253,9 @@ static int dst_dev_event(struct notifier_block *this, unsigned long event, void
struct net_device *dev = ptr;
struct dst_entry *dst;
+ if (dev->nd_net != &init_net)
+ return NOTIFY_DONE;
+
switch (event) {
case NETDEV_UNREGISTER:
case NETDEV_DOWN:
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 8c5474e..9eabe1a 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -11,6 +11,7 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/list.h>
+#include <net/net_namespace.h>
#include <net/fib
...
|
|
|
[PATCH 12/16] net: Support multiple network namespaces with netlink [message #19978 is a reply to message #19977] |
Sat, 08 September 2007 21:28 |
ebiederm
Messages: 1354 Registered: February 2006
|
Senior Member |
|
|
Each netlink socket will live in exactly one network namespace,
this includes the controlling kernel sockets.
This patch updates all of the existing netlink protocols
to only support the initial network namespace. Request
by clients in other namespaces will get -ECONREFUSED.
As they would if the kernel did not have the support for
that netlink protocol compiled in.
As each netlink protocol is updated to be multiple network
namespace safe it can register multiple kernel sockets
to acquire a presence in the rest of the network namespaces.
The implementation in af_netlink is a simple filter implementation
at hash table insertion and hash table look up time.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
drivers/connector/connector.c | 2 +-
drivers/scsi/scsi_netlink.c | 2 +-
drivers/scsi/scsi_transport_iscsi.c | 2 +-
fs/ecryptfs/netlink.c | 2 +-
include/linux/netlink.h | 6 ++-
kernel/audit.c | 4 +-
lib/kobject_uevent.c | 5 +-
net/bridge/netfilter/ebt_ulog.c | 5 +-
net/core/rtnetlink.c | 4 +-
net/decnet/netfilter/dn_rtmsg.c | 3 +-
net/ipv4/fib_frontend.c | 4 +-
net/ipv4/inet_diag.c | 4 +-
net/ipv4/netfilter/ip_queue.c | 6 +-
net/ipv4/netfilter/ipt_ULOG.c | 3 +-
net/ipv6/netfilter/ip6_queue.c | 6 +-
net/netfilter/nfnetlink.c | 2 +-
net/netfilter/nfnetlink_log.c | 3 +-
net/netfilter/nfnetlink_queue.c | 3 +-
net/netlink/af_netlink.c | 106 ++++++++++++++++++++++++++---------
net/netlink/genetlink.c | 4 +-
net/xfrm/xfrm_user.c | 2 +-
security/selinux/netlink.c | 5 +-
22 files changed, 122 insertions(+), 61 deletions(-)
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
index a7b9e9b..5690709 100644
--- a/drivers/connector/connector.c
+++ b/drivers/connector/connector.c
@@ -446,7 +446,7 @@ static int __devinit cn_init(void)
dev->id.idx = cn_idx;
dev->id.val = cn_val;
- dev->nls = netlink_kernel_create(NETLINK_CONNECTOR,
+ dev->nls = netlink_kernel_create(&init_net, NETLINK_CONNECTOR,
CN_NETLINK_USERS + 0xf,
dev->input, NULL, THIS_MODULE);
if (!dev->nls)
diff --git a/drivers/scsi/scsi_netlink.c b/drivers/scsi/scsi_netlink.c
index 4bf9aa5..163acf6 100644
--- a/drivers/scsi/scsi_netlink.c
+++ b/drivers/scsi/scsi_netlink.c
@@ -167,7 +167,7 @@ scsi_netlink_init(void)
return;
}
- scsi_nl_sock = netlink_kernel_create(NETLINK_SCSITRANSPORT,
+ scsi_nl_sock = netlink_kernel_create(&init_net, NETLINK_SCSITRANSPORT,
SCSI_NL_GRP_CNT, scsi_nl_rcv, NULL,
THIS_MODULE);
if (!scsi_nl_sock) {
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 34c1860..4916f01 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -1523,7 +1523,7 @@ static __init int iscsi_transport_init(void)
if (err)
goto unregister_conn_class;
- nls = netlink_kernel_create(NETLINK_ISCSI, 1, iscsi_if_rx, NULL,
+ nls = netlink_kernel_create(&init_net, NETLINK_ISCSI, 1, iscsi_if_rx, NULL,
THIS_MODULE);
if (!nls) {
err = -ENOBUFS;
diff --git a/fs/ecryptfs/netlink.c b/fs/ecryptfs/netlink.c
index fe91863..056519c 100644
--- a/fs/ecryptfs/netlink.c
+++ b/fs/ecryptfs/netlink.c
@@ -227,7 +227,7 @@ int ecryptfs_init_netlink(void)
{
int rc;
- ecryptfs_nl_sock = netlink_kernel_create(NETLINK_ECRYPTFS, 0,
+ ecryptfs_nl_sock = netlink_kernel_create(&init_net, NETLINK_ECRYPTFS, 0,
ecryptfs_receive_nl_message,
NULL, THIS_MODULE);
if (!ecryptfs_nl_sock) {
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index 83d8239..d2843ae 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -27,6 +27,8 @@
#define MAX_LINKS 32
+struct net;
+
struct sockaddr_nl
{
sa_family_t nl_family; /* AF_NETLINK */
@@ -157,7 +159,8 @@ struct netlink_skb_parms
#define NETLINK_CREDS(skb) (&NETLINK_CB((skb)).creds)
-extern struct sock *netlink_kernel_create(int unit, unsigned int groups,
+extern struct sock *netlink_kernel_create(struct net *net,
+ int unit,unsigned int groups,
void (*input)(struct sock *sk, int len),
struct mutex *cb_mutex,
struct module *module);
@@ -206,6 +209,7 @@ struct netlink_callback
struct netlink_notify
{
+ struct net *net;
int pid;
int protocol;
};
diff --git a/kernel/audit.c b/kernel/audit.c
index eb0f916..f3c390f 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -876,8 +876,8 @@ static int __init audit_init(void)
printk(KERN_INFO "audit: initializing netlink socket (%s)\n",
audit_default ? "enabled" : "disabled");
- audit_sock = netlink_kernel_create(NETLINK_AUDIT, 0, audit_receive,
- NULL, THIS_MODULE);
+ audit_sock = netlink_kernel_create(&init_net, NETLINK_AUDIT, 0,
+ audit_receive, NULL, THIS_MODULE);
if (!audit_sock)
audit_panic("cannot initialize netlink socket");
else
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index df02814..e06a8dc 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -280,9 +280,8 @@ EXPORT_SYMBOL_GPL(add_uevent_var);
#if defined(CONFIG_NET)
static int __init kobject_uevent_init(void)
{
- uevent_sock = netlink_kernel_create(NETLINK_KOBJECT_UEVENT, 1, NULL,
- NULL, THIS_MODULE);
-
+ uevent_sock = netlink_kernel_create(&init_net, NETLINK_KOBJECT_UEVENT,
+ 1, NULL, NULL, THIS_MODULE);
if (!uevent_sock) {
printk(KERN_ERR
"kobject_uevent: unable to create netlink socket!\n");
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c
index 204c968..e7cfd30 100644
--- a/net/bridge/netfilter/ebt_ulog.c
+++ b/net/bridge/netfilter/ebt_ulog.c
@@ -300,8 +300,9 @@ static int __init ebt_ulog_init(void)
spin_lock_init(&ulog_buffers[i].lock);
}
- ebtulognl = netlink_kernel_create(NETLINK_NFLOG, EBT_ULOG_MAXNLGROUPS,
- NULL, NULL, THIS_MODULE);
+ ebtulognl = netlink_kernel_create(&init_net, NETLINK_NFLOG,
+ EBT_ULOG_MAXNLGROUPS, NULL, NULL,
+ THIS_MODULE);
if (!ebtulognl)
ret = -ENOMEM;
else if ((ret = ebt_register_watcher(&ulog)))
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 4185950..416768d 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1327,8 +1327,8 @@ void __init rtnetlink_init(void)
if (!rta_buf)
panic("rtnetlink_init: cannot allocate rta_buf\n");
- rtnl = netlink_kernel_create(NETLINK_ROUTE, RTNLGRP_MAX, rtnetlink_rcv,
- &rtnl_mutex, THIS_MODULE);
+ rtnl = netlink_kernel_create(&init_net, NETLINK_ROUTE, RTNLGRP_MAX,
+ rtnetlink_rcv, &rtnl_mutex, THIS_MODULE);
if (rtnl == NULL)
panic("rtnetlink_init: cannot initialize rtnetlink\n");
netlink_set_nonroot(NETLINK_ROUTE, NL_NONROOT_RECV);
diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c
index 6962346..ebb38fe 100644
--- a/net/decnet/netfilter/dn_rtmsg.c
+++ b/net/decnet/netfilter/dn_rtmsg.c
@@ -137,7 +137,8 @@ static int __init dn_rtmsg_init(void)
{
int rv = 0;
- dnrmg = netlink_kernel_create(NETLINK_DNRTMSG, DNRNG_NLGRP_MAX,
+ dnrmg = netlink_kernel_create(&init_net,
+ NETLINK_DNRTMSG, DNRNG_NLGRP_MAX,
dnrmg_receive_user_sk, NULL, THIS_MODULE);
if (dnrmg == NULL) {
printk(KERN_ERR "dn_rtmsg: Cannot create netlink socket");
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index cefb55e..140bf7a 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -816,8 +816,8 @@ static void nl_fib_input(struct sock *sk, int len)
static void nl_fib_lookup_init(void)
{
- netlink_kernel_create(NETLINK_FIB_LOOKUP, 0, nl_fib_input, NULL,
- THIS_MODULE);
+ netlink_kernel_create(&init_net, NETLINK_FIB_LOOKUP, 0, nl_fib_input,
+ NULL, THIS_MODULE);
}
static void fib_disable_ip(struct net_device *dev, int force)
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index 06922da..169026d 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -893,8 +893,8 @@ static int __init inet_diag_init(void)
if (!inet_diag_table)
goto out;
- idiagnl = netlink_kernel_create(NETLINK_INET_DIAG, 0, inet_diag_rcv,
- NULL, THIS_MODULE);
+ idiagnl = netlink_kernel_create(&init_net, NETLINK_INET_DIAG, 0,
+ inet_diag_rcv, NULL, THIS_MODULE);
if (idiagnl == NULL)
goto out_free_table;
err = 0;
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index d918560..82fda92 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -579,7 +579,7 @@ ipq_rcv_nl_event(struct notifier_block *this,
if (event == NETLINK_URELEASE &&
n->protocol == NETLINK_FIREWALL && n->pid) {
write_lock_bh(&queue_lock);
- if (n->pid == peer_pid)
+ if ((n->net == &init_net) && (n->pid == peer_pid))
__ipq_reset();
write_unlock_bh(&queue_lock);
}
@@ -671,8 +671,8 @@ static int __init ip_queue_init(void)
struct proc_dir_entry *proc;
netlink_register_notifier(&ipq_nl_notifier);
- ipqnl = netlink_kernel_create(NETLINK_FIREWALL, 0, ipq_rcv_sk,
- NULL, THIS_MODULE);
+ ipqnl = netlink_kernel_create(&init_net, NETLINK_FIREWALL, 0,
+ ipq_rcv_sk, NULL, THIS_MODULE);
if (ipqnl == NULL) {
printk(KERN_ERR "ip_queue: failed to create netlink socket\n");
goto cleanup_netlink_notifier;
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index 6ca43e4..c636d6d 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -409,7 +409,8 @@ static int __init ipt_ulog_init(void)
for (i = 0; i < ULOG_MAXNLGROUPS; i++)
...
|
|
|
[PATCH 13/16] net: Make the device list and device lookups per namespace. [message #19979 is a reply to message #19978] |
Sat, 08 September 2007 21:35 |
ebiederm
Messages: 1354 Registered: February 2006
|
Senior Member |
|
|
This patch makes most of the generic device layer network
namespace safe. This patch makes dev_base_head a
network namespace variable, and then it picks up
a few associated variables. The functions:
dev_getbyhwaddr
dev_getfirsthwbytype
dev_get_by_flags
dev_get_by_name
__dev_get_by_name
dev_get_by_index
__dev_get_by_index
dev_ioctl
dev_ethtool
dev_load
wireless_process_ioctl
were modified to take a network namespace argument, and
deal with it.
vlan_ioctl_set and brioctl_set were modified so their
hooks will receive a network namespace argument.
So basically anthing in the core of the network stack that was
affected to by the change of dev_base was modified to handle
multiple network namespaces. The rest of the network stack was
simply modified to explicitly use &init_net the initial network
namespace. This can be fixed when those components of the network
stack are modified to handle multiple network namespaces.
For now the ifindex generator is left global.
Fundametally ifindex numbers are per namespace, or else
we will have corner case problems with migration when
we get that far.
At the same time there are assumptions in the network stack
that the ifindex of a network device won't change. Making
the ifindex number global seems a good compromise until
the network stack can cope with ifindex changes when
you change namespaces, and the like.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
arch/s390/appldata/appldata_net_sum.c | 3 +-
arch/sparc64/solaris/ioctl.c | 3 +-
drivers/atm/idt77252.c | 2 +-
drivers/block/aoe/aoecmd.c | 3 +-
drivers/infiniband/hw/cxgb3/cxio_hal.c | 3 +-
drivers/net/bonding/bond_main.c | 2 +-
drivers/net/bonding/bond_sysfs.c | 3 +-
drivers/net/eql.c | 9 +-
drivers/net/ifb.c | 3 +-
drivers/net/macvlan.c | 2 +-
drivers/net/pppoe.c | 4 +-
drivers/net/shaper.c | 3 +-
drivers/net/tun.c | 3 +-
drivers/net/veth.c | 2 +-
drivers/net/wan/dlci.c | 4 +-
drivers/net/wan/sbni.c | 3 +-
drivers/net/wireless/strip.c | 2 +-
drivers/parisc/led.c | 2 +-
fs/afs/netdevices.c | 5 +-
include/linux/if_bridge.h | 2 +-
include/linux/if_vlan.h | 2 +-
include/linux/netdevice.h | 66 ++++----
include/net/net_namespace.h | 4 +
include/net/pkt_cls.h | 3 +-
include/net/rtnetlink.h | 2 +-
include/net/wext.h | 15 ++-
net/802/tr.c | 2 +-
net/8021q/vlan.c | 6 +-
net/8021q/vlan_netlink.c | 3 +-
net/8021q/vlanproc.c | 6 +-
net/appletalk/ddp.c | 6 +-
net/atm/mpc.c | 2 +-
net/ax25/af_ax25.c | 2 +-
net/bridge/br_if.c | 4 +-
net/bridge/br_ioctl.c | 7 +-
net/bridge/br_netlink.c | 5 +-
net/bridge/br_private.h | 2 +-
net/core/dev.c | 271 +++++++++++++++++++++-----------
net/core/dev_mcast.c | 41 +++++-
net/core/ethtool.c | 4 +-
net/core/fib_rules.c | 4 +-
net/core/neighbour.c | 6 +-
net/core/netpoll.c | 2 +-
net/core/pktgen.c | 2 +-
net/core/rtnetlink.c | 35 +++--
net/core/sock.c | 3 +-
net/decnet/af_decnet.c | 2 +-
net/decnet/dn_dev.c | 20 ++--
net/decnet/dn_fib.c | 8 +-
net/decnet/dn_route.c | 6 +-
net/decnet/sysctl_net_decnet.c | 4 +-
net/econet/af_econet.c | 2 +-
net/ipv4/arp.c | 4 +-
net/ipv4/devinet.c | 18 +-
net/ipv4/fib_frontend.c | 2 +-
net/ipv4/fib_semantics.c | 4 +-
net/ipv4/icmp.c | 2 +-
net/ipv4/igmp.c | 4 +-
net/ipv4/ip_fragment.c | 2 +-
net/ipv4/ip_gre.c | 4 +-
net/ipv4/ip_sockglue.c | 2 +-
net/ipv4/ipconfig.c | 2 +-
net/ipv4/ipip.c | 4 +-
net/ipv4/ipmr.c | 4 +-
net/ipv4/ipvs/ip_vs_sync.c | 10 +-
net/ipv4/netfilter/ipt_CLUSTERIP.c | 2 +-
net/ipv4/route.c | 4 +-
net/ipv6/addrconf.c | 28 ++--
net/ipv6/af_inet6.c | 2 +-
net/ipv6/anycast.c | 12 +-
net/ipv6/datagram.c | 2 +-
net/ipv6/ip6_tunnel.c | 6 +-
net/ipv6/ipv6_sockglue.c | 2 +-
net/ipv6/mcast.c | 12 +-
net/ipv6/raw.c | 2 +-
net/ipv6/reassembly.c | 2 +-
net/ipv6/route.c | 4 +-
net/ipv6/sit.c | 4 +-
net/ipx/af_ipx.c | 6 +-
net/irda/irnetlink.c | 9 +-
net/llc/af_llc.c | 4 +-
net/llc/llc_core.c | 3 +-
net/mac80211/ieee80211.c | 1 +
net/mac80211/ieee80211_cfg.c | 3 +-
net/mac80211/tx.c | 9 +-
net/mac80211/util.c | 7 +-
net/netrom/nr_route.c | 6 +-
net/packet/af_packet.c | 18 +-
net/rose/rose_route.c | 8 +-
net/sched/act_mirred.c | 3 +-
net/sched/cls_api.c | 4 +-
net/sched/em_meta.c | 2 +-
net/sched/sch_api.c | 10 +-
net/sctp/ipv6.c | 4 +-
net/sctp/protocol.c | 2 +-
net/socket.c | 22 ++-
net/tipc/eth_media.c | 2 +-
net/wireless/wext.c | 38 ++++-
net/x25/x25_route.c | 2 +-
99 files changed, 555 insertions(+), 362 deletions(-)
diff --git a/arch/s390/appldata/appldata_net_sum.c b/arch/s390/appldata/appldata_net_sum.c
index 2180ac1..6c1815a 100644
--- a/arch/s390/appldata/appldata_net_sum.c
+++ b/arch/s390/appldata/appldata_net_sum.c
@@ -16,6 +16,7 @@
#include <linux/errno.h>
#include <linux/kernel_stat.h>
#include <linux/netdevice.h>
+#include <net/net_namespace.h>
#include "appldata.h"
@@ -107,7 +108,7 @@ static void appldata_get_net_sum_data(void *data)
tx_dropped = 0;
collisions = 0;
read_lock(&dev_base_lock);
- for_each_netdev(dev) {
+ for_each_netdev(&init_net, dev) {
stats = dev->get_stats(dev);
rx_packets += stats->rx_packets;
tx_packets += stats->tx_packets;
diff --git a/arch/sparc64/solaris/ioctl.c b/arch/sparc64/solaris/ioctl.c
index 18352a4..8ad10a6 100644
--- a/arch/sparc64/solaris/ioctl.c
+++ b/arch/sparc64/solaris/ioctl.c
@@ -28,6 +28,7 @@
#include <linux/compat.h>
#include <net/sock.h>
+#include <net/net_namespace.h>
#include <asm/uaccess.h>
#include <asm/termios.h>
@@ -686,7 +687,7 @@ static inline int solaris_i(unsigned int fd, unsigned int cmd, u32 arg)
int i = 0;
read_lock_bh(&dev_base_lock);
- for_each_netdev(d)
+ for_each_netdev(&init_net, d)
i++;
read_unlock_bh(&dev_base_lock);
diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c
index f8b1700..eee54c0 100644
--- a/drivers/atm/idt77252.c
+++ b/drivers/atm/idt77252.c
@@ -3576,7 +3576,7 @@ init_card(struct atm_dev *dev)
* XXX: <hack>
*/
sprintf(tname, "eth%d", card->index);
- tmp = dev_get_by_name(tname); /* jhs: was "tmp = dev_get(tname);" */
+ tmp = dev_get_by_name(&init_net, tname); /* jhs: was "tmp = dev_get(tname);" */
if (tmp) {
memcpy(card->atmdev->esi, tmp->dev_addr, 6);
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
index 01fbdd3..30394f7 100644
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -9,6 +9,7 @@
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/genhd.h>
+#include <net/net_namespace.h>
#include <asm/unaligned.h>
#include "aoe.h"
@@ -194,7 +195,7 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail)
sl = sl_tail = NULL;
read_lock(&dev_base_lock);
- for_each_netdev(ifp) {
+ for_each_netdev(&init_net, ifp) {
dev_hold(ifp);
if (!is_aoe_netif(ifp))
goto cont;
diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.c b/drivers/infiniband/hw/cxgb3/cxio_hal.c
index 1518b41..7b92b7d 100644
--- a/drivers/infiniband/hw/cxgb3/cxio_hal.c
+++ b/drivers/infiniband/hw/cxgb3/cxio_hal.c
@@ -37,6 +37,7 @@
#include <linux/spinlock.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
+#include <net/net_namespace.h>
#include "cxio_resource.h"
#include "cxio_hal.h"
@@ -894,7 +895,7 @@ int cxio_rdev_open(struct cxio_rdev *rdev_p)
if (cxio_hal_find_rdev_by_name(rdev_p->dev_name)) {
return -EBUSY;
}
- netdev_p = dev_get_by_name(rdev_p->dev_name);
+ netdev_p = dev_get_by_name(&init_net, rdev_p->dev_name);
if (!netdev_p) {
return -EINVAL;
}
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index cf97d8a..559fe94 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3719,7
...
|
|
|
[PATCH 14/16] net: Factor out __dev_alloc_name from dev_alloc_name [message #19980 is a reply to message #19979] |
Sat, 08 September 2007 21:36 |
ebiederm
Messages: 1354 Registered: February 2006
|
Senior Member |
|
|
When forcibly changing the network namespace of a device
I need something that can generate a name for the device
in the new namespace without overwriting the old name.
__dev_alloc_name provides me that functionality.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
net/core/dev.c | 48 +++++++++++++++++++++++++++++++++++-------------
1 files changed, 35 insertions(+), 13 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index c51cf40..53cdb64 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -739,9 +739,10 @@ int dev_valid_name(const char *name)
}
/**
- * dev_alloc_name - allocate a name for a device
- * @dev: device
+ * __dev_alloc_name - allocate a name for a device
+ * @net: network namespace to allocate the device name in
* @name: name format string
+ * @buf: scratch buffer and result name string
*
* Passed a format string - eg "lt%d" it will try and find a suitable
* id. It scans list of devices to build up a free map, then chooses
@@ -752,18 +753,13 @@ int dev_valid_name(const char *name)
* Returns the number of the unit assigned or a negative errno code.
*/
-int dev_alloc_name(struct net_device *dev, const char *name)
+static int __dev_alloc_name(struct net *net, const char *name, char *buf)
{
int i = 0;
- char buf[IFNAMSIZ];
const char *p;
const int max_netdevices = 8*PAGE_SIZE;
long *inuse;
struct net_device *d;
- struct net *net;
-
- BUG_ON(!dev->nd_net);
- net = dev->nd_net;
p = strnchr(name, IFNAMSIZ-1, '%');
if (p) {
@@ -787,7 +783,7 @@ int dev_alloc_name(struct net_device *dev, const char *name)
continue;
/* avoid cases where sscanf is not exact inverse of printf */
- snprintf(buf, sizeof(buf), name, i);
+ snprintf(buf, IFNAMSIZ, name, i);
if (!strncmp(buf, d->name, IFNAMSIZ))
set_bit(i, inuse);
}
@@ -796,11 +792,9 @@ int dev_alloc_name(struct net_device *dev, const char *name)
free_page((unsigned long) inuse);
}
- snprintf(buf, sizeof(buf), name, i);
- if (!__dev_get_by_name(net, buf)) {
- strlcpy(dev->name, buf, IFNAMSIZ);
+ snprintf(buf, IFNAMSIZ, name, i);
+ if (!__dev_get_by_name(net, buf))
return i;
- }
/* It is possible to run out of possible slots
* when the name is long and there isn't enough space left
@@ -809,6 +803,34 @@ int dev_alloc_name(struct net_device *dev, const char *name)
return -ENFILE;
}
+/**
+ * dev_alloc_name - allocate a name for a device
+ * @dev: device
+ * @name: name format string
+ *
+ * Passed a format string - eg "lt%d" it will try and find a suitable
+ * id. It scans list of devices to build up a free map, then chooses
+ * the first empty slot. The caller must hold the dev_base or rtnl lock
+ * while allocating the name and adding the device in order to avoid
+ * duplicates.
+ * Limited to bits_per_byte * page size devices (ie 32K on most platforms).
+ * Returns the number of the unit assigned or a negative errno code.
+ */
+
+int dev_alloc_name(struct net_device *dev, const char *name)
+{
+ char buf[IFNAMSIZ];
+ struct net *net;
+ int ret;
+
+ BUG_ON(!dev->nd_net);
+ net = dev->nd_net;
+ ret = __dev_alloc_name(net, name, buf);
+ if (ret >= 0)
+ strlcpy(dev->name, buf, IFNAMSIZ);
+ return ret;
+}
+
/**
* dev_change_name - change name of a device
--
1.5.3.rc6.17.g1911
_______________________________________________
Containers mailing list
Containers@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/containers
|
|
|
[PATCH 15/16] net: Implement network device movement between namespaces [message #19981 is a reply to message #19980] |
Sat, 08 September 2007 21:38 |
ebiederm
Messages: 1354 Registered: February 2006
|
Senior Member |
|
|
This patch introduces NETIF_F_NETNS_LOCAL a flag to indicate
a network device is local to a single network namespace and
should never be moved. Useful for pseudo devices that we
need an instance in each network namespace (like the loopback
device) and for any device we find that cannot handle multiple
network namespaces so we may trap them in the initial network
namespace.
This patch introduces the function dev_change_net_namespace
a function used to move a network device from one network
namespace to another. To the network device nothing
special appears to happen, to the components of the network
stack it appears as if the network device was unregistered
in the network namespace it is in, and a new device
was registered in the network namespace the device
was moved to.
This patch sets up a namespace device destructor that
upon the exit of a network namespace moves all of the
movable network devices to the initial network namespace
so they are not lost.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
drivers/net/loopback.c | 3 +-
include/linux/netdevice.h | 3 +
net/core/dev.c | 189 ++++++++++++++++++++++++++++++++++++++++++---
3 files changed, 184 insertions(+), 11 deletions(-)
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index 5106c23..e399f7b 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -222,7 +222,8 @@ struct net_device loopback_dev = {
| NETIF_F_TSO
#endif
| NETIF_F_NO_CSUM | NETIF_F_HIGHDMA
- | NETIF_F_LLTX,
+ | NETIF_F_LLTX
+ | NETIF_F_NETNS_LOCAL,
.ethtool_ops = &loopback_ethtool_ops,
};
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index ec90d1a..d33d897 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -435,6 +435,7 @@ struct net_device
#define NETIF_F_VLAN_CHALLENGED 1024 /* Device cannot handle VLAN packets */
#define NETIF_F_GSO 2048 /* Enable software GSO. */
#define NETIF_F_LLTX 4096 /* LockLess TX */
+#define NETIF_F_NETNS_LOCAL 8192 /* Does not change network namespaces */
#define NETIF_F_MULTI_QUEUE 16384 /* Has multiple TX/RX queues */
#define NETIF_F_LRO 32768 /* large receive offload */
@@ -1002,6 +1003,8 @@ extern int dev_ethtool(struct net *net, struct ifreq *);
extern unsigned dev_get_flags(const struct net_device *);
extern int dev_change_flags(struct net_device *, unsigned);
extern int dev_change_name(struct net_device *, char *);
+extern int dev_change_net_namespace(struct net_device *,
+ struct net *, const char *);
extern int dev_set_mtu(struct net_device *, int);
extern int dev_set_mac_address(struct net_device *,
struct sockaddr *);
diff --git a/net/core/dev.c b/net/core/dev.c
index 53cdb64..d82ec5a 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -208,6 +208,34 @@ static inline struct hlist_head *dev_index_hash(struct net *net, int ifindex)
return &net->dev_index_head[ifindex & ((1 << NETDEV_HASHBITS) - 1)];
}
+/* Device list insertion */
+static int list_netdevice(struct net_device *dev)
+{
+ struct net *net = dev->nd_net;
+
+ ASSERT_RTNL();
+
+ write_lock_bh(&dev_base_lock);
+ list_add_tail(&dev->dev_list, &net->dev_base_head);
+ hlist_add_head(&dev->name_hlist, dev_name_hash(net, dev->name));
+ hlist_add_head(&dev->index_hlist, dev_index_hash(net, dev->ifindex));
+ write_unlock_bh(&dev_base_lock);
+ return 0;
+}
+
+/* Device list removal */
+static void unlist_netdevice(struct net_device *dev)
+{
+ ASSERT_RTNL();
+
+ /* Unlink dev from the device chain */
+ write_lock_bh(&dev_base_lock);
+ list_del(&dev->dev_list);
+ hlist_del(&dev->name_hlist);
+ hlist_del(&dev->index_hlist);
+ write_unlock_bh(&dev_base_lock);
+}
+
/*
* Our notifier list
*/
@@ -3553,12 +3581,8 @@ int register_netdevice(struct net_device *dev)
set_bit(__LINK_STATE_PRESENT, &dev->state);
dev_init_scheduler(dev);
- write_lock_bh(&dev_base_lock);
- list_add_tail(&dev->dev_list, &net->dev_base_head);
- hlist_add_head(&dev->name_hlist, head);
- hlist_add_head(&dev->index_hlist, dev_index_hash(net, dev->ifindex));
dev_hold(dev);
- write_unlock_bh(&dev_base_lock);
+ list_netdevice(dev);
/* Notify protocols, that a new device appeared. */
ret = raw_notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);
@@ -3865,11 +3889,7 @@ void unregister_netdevice(struct net_device *dev)
dev_close(dev);
/* And unlink it from device chain. */
- write_lock_bh(&dev_base_lock);
- list_del(&dev->dev_list);
- hlist_del(&dev->name_hlist);
- hlist_del(&dev->index_hlist);
- write_unlock_bh(&dev_base_lock);
+ unlist_netdevice(dev);
dev->reg_state = NETREG_UNREGISTERING;
@@ -3927,6 +3947,122 @@ void unregister_netdev(struct net_device *dev)
EXPORT_SYMBOL(unregister_netdev);
+/**
+ * dev_change_net_namespace - move device to different nethost namespace
+ * @dev: device
+ * @net: network namespace
+ * @pat: If not NULL name pattern to try if the current device name
+ * is already taken in the destination network namespace.
+ *
+ * This function shuts down a device interface and moves it
+ * to a new network namespace. On success 0 is returned, on
+ * a failure a netagive errno code is returned.
+ *
+ * Callers must hold the rtnl semaphore.
+ */
+
+int dev_change_net_namespace(struct net_device *dev, struct net *net, const char *pat)
+{
+ char buf[IFNAMSIZ];
+ const char *destname;
+ int err;
+
+ ASSERT_RTNL();
+
+ /* Don't allow namespace local devices to be moved. */
+ err = -EINVAL;
+ if (dev->features & NETIF_F_NETNS_LOCAL)
+ goto out;
+
+ /* Ensure the device has been registrered */
+ err = -EINVAL;
+ if (dev->reg_state != NETREG_REGISTERED)
+ goto out;
+
+ /* Get out if there is nothing todo */
+ err = 0;
+ if (dev->nd_net == net)
+ goto out;
+
+ /* Pick the destination device name, and ensure
+ * we can use it in the destination network namespace.
+ */
+ err = -EEXIST;
+ destname = dev->name;
+ if (__dev_get_by_name(net, destname)) {
+ /* We get here if we can't use the current device name */
+ if (!pat)
+ goto out;
+ if (!dev_valid_name(pat))
+ goto out;
+ if (strchr(pat, '%')) {
+ if (__dev_alloc_name(net, pat, buf) < 0)
+ goto out;
+ destname = buf;
+ } else
+ destname = pat;
+ if (__dev_get_by_name(net, destname))
+ goto out;
+ }
+
+ /*
+ * And now a mini version of register_netdevice unregister_netdevice.
+ */
+
+ /* If device is running close it first. */
+ if (dev->flags & IFF_UP)
+ dev_close(dev);
+
+ /* And unlink it from device chain */
+ err = -ENODEV;
+ unlist_netdevice(dev);
+
+ synchronize_net();
+
+ /* Shutdown queueing discipline. */
+ dev_shutdown(dev);
+
+ /* Notify protocols, that we are about to destroy
+ this device. They should clean all the things.
+ */
+ call_netdevice_notifiers(NETDEV_UNREGISTER, dev);
+
+ /*
+ * Flush the unicast and multicast chains
+ */
+ dev_addr_discard(dev);
+
+ /* Actually switch the network namespace */
+ dev->nd_net = net;
+
+ /* Assign the new device name */
+ if (destname != dev->name)
+ strcpy(dev->name, destname);
+
+ /* If there is an ifindex conflict assign a new one */
+ if (__dev_get_by_index(net, dev->ifindex)) {
+ int iflink = (dev->iflink == dev->ifindex);
+ dev->ifindex = dev_new_index(net);
+ if (iflink)
+ dev->iflink = dev->ifindex;
+ }
+
+ /* Fixup sysfs */
+ err = device_rename(&dev->dev, dev->name);
+ BUG_ON(err);
+
+ /* Add the device back in the hashes */
+ list_netdevice(dev);
+
+ /* Notify protocols, that a new device appeared. */
+ call_netdevice_notifiers(NETDEV_REGISTER, dev);
+
+ synchronize_net();
+ err = 0;
+out:
+ return err;
+}
+
static int dev_cpu_callback(struct notifier_block *nfb,
unsigned long action,
void *ocpu)
@@ -4159,6 +4295,36 @@ static struct pernet_operations netdev_net_ops = {
.exit = netdev_exit,
};
+static void default_device_exit(struct net *net)
+{
+ struct net_device *dev, *next;
+ /*
+ * Push all migratable of the network devices back to the
+ * initial network namespace
+ */
+ rtnl_lock();
+ for_each_netdev_safe(net, dev, next) {
+ int err;
+
+ /* Ignore unmoveable devices (i.e. loopback) */
+ if (dev->features & NETIF_F_NETNS_LOCAL)
+ continue;
+
+ /* Push remaing network devices to init_net */
+ err = dev_change_net_namespace(dev, &init_net, "dev%d");
+ if (err) {
+ printk(KERN_WARNING "%s: failed to move %s to init_net: %d\n",
+ __func__, dev->name, err);
+ unregister_netdevice(dev);
+ }
+ }
+ rtnl_unlock();
+}
+
+static struct pernet_operations default_device_ops = {
+ .exit = default_device_exit,
+};
+
/*
* Initialize the DEV module. At boot time this walks the device list and
* unhooks any devices that fail to initialise (normally hardware not
@@ -4189,6 +4355,9 @@ static int __init net_dev_init(void)
if (register_pernet_subsys(&netdev_net_ops))
goto out;
+ if (register_pernet_device(&default_device_ops))
+ goto out;
+
/*
* Initialise the packet receive queues.
*/
--
1.5.3.rc6.17.g1911
_______________________________________________
Containers mailing list
Containers@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/containers
|
|
|
[PATCH 16/16] net: netlink support for moving devices between network namespaces. [message #19982 is a reply to message #19981] |
Sat, 08 September 2007 21:43 |
ebiederm
Messages: 1354 Registered: February 2006
|
Senior Member |
|
|
The simplest thing to implement is moving network devices between
namespaces. However with the same attribute IFLA_NET_NS_PID we can
easily implement creating devices in the destination network
namespace as well. However that is a little bit trickier so this
patch sticks to what is simple and easy.
A pid is used to identify a process that happens to be a member
of the network namespace we want to move the network device to.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
include/linux/if_link.h | 1 +
net/core/rtnetlink.c | 35 +++++++++++++++++++++++++++++++++++
2 files changed, 36 insertions(+), 0 deletions(-)
diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index 422084d..84c3492 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -78,6 +78,7 @@ enum
IFLA_LINKMODE,
IFLA_LINKINFO,
#define IFLA_LINKINFO IFLA_LINKINFO
+ IFLA_NET_NS_PID,
__IFLA_MAX
};
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 44f91bb..1b9c32d 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -35,6 +35,7 @@
#include <linux/security.h>
#include <linux/mutex.h>
#include <linux/if_addr.h>
+#include <linux/nsproxy.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -727,6 +728,7 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = {
[IFLA_WEIGHT] = { .type = NLA_U32 },
[IFLA_OPERSTATE] = { .type = NLA_U8 },
[IFLA_LINKMODE] = { .type = NLA_U8 },
+ [IFLA_NET_NS_PID] = { .type = NLA_U32 },
};
static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
@@ -734,12 +736,45 @@ static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
[IFLA_INFO_DATA] = { .type = NLA_NESTED },
};
+static struct net *get_net_ns_by_pid(pid_t pid)
+{
+ struct task_struct *tsk;
+ struct net *net;
+
+ /* Lookup the network namespace */
+ net = ERR_PTR(-ESRCH);
+ rcu_read_lock();
+ tsk = find_task_by_pid(pid);
+ if (tsk) {
+ task_lock(tsk);
+ if (tsk->nsproxy)
+ net = get_net(tsk->nsproxy->net_ns);
+ task_unlock(tsk);
+ }
+ rcu_read_unlock();
+ return net;
+}
+
static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
struct nlattr **tb, char *ifname, int modified)
{
int send_addr_notify = 0;
int err;
+ if (tb[IFLA_NET_NS_PID]) {
+ struct net *net;
+ net = get_net_ns_by_pid(nla_get_u32(tb[IFLA_NET_NS_PID]));
+ if (IS_ERR(net)) {
+ err = PTR_ERR(net);
+ goto errout;
+ }
+ err = dev_change_net_namespace(dev, net, ifname);
+ put_net(net);
+ if (err)
+ goto errout;
+ modified = 1;
+ }
+
if (tb[IFLA_MAP]) {
struct rtnl_link_ifmap *u_map;
struct ifmap k_map;
--
1.5.3.rc6.17.g1911
_______________________________________________
Containers mailing list
Containers@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/containers
|
|
|
[PATCH 17/16] net: Disable netfilter sockopts when not in the initial network namespace [message #19983 is a reply to message #19982] |
Sat, 08 September 2007 21:47 |
ebiederm
Messages: 1354 Registered: February 2006
|
Senior Member |
|
|
Until we support multiple network namespaces with netfilter only allow
netfilter configuration in the initial network namespace.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
Ooops I overlooked this one on my first path through when gathering up this
patchset.
net/netfilter/nf_sockopt.c | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/net/netfilter/nf_sockopt.c b/net/netfilter/nf_sockopt.c
index 8b8ece7..c12ea9b 100644
--- a/net/netfilter/nf_sockopt.c
+++ b/net/netfilter/nf_sockopt.c
@@ -80,6 +80,9 @@ static int nf_sockopt(struct sock *sk, int pf, int val,
struct nf_sockopt_ops *ops;
int ret;
+ if (sk->sk_net != &init_net)
+ return -ENOPROTOOPT;
+
if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0)
return -EINTR;
@@ -138,6 +141,10 @@ static int compat_nf_sockopt(struct sock *sk, int pf, int val,
struct nf_sockopt_ops *ops;
int ret;
+ if (sk->sk_net != &init_net)
+ return -ENOPROTOOPT;
+
+
if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0)
return -EINTR;
--
1.5.3.rc6.17.g1911
_______________________________________________
Containers mailing list
Containers@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/containers
|
|
|
Re: [PATCH 03/16] net: Basic network namespace infrastructure. [message #19984 is a reply to message #19969] |
Sun, 09 September 2007 00:33 |
paulmck
Messages: 13 Registered: August 2006
|
Junior Member |
|
|
On Sat, Sep 08, 2007 at 03:15:34PM -0600, Eric W. Biederman wrote:
>
> This is the basic infrastructure needed to support network
> namespaces. This infrastructure is:
> - Registration functions to support initializing per network
> namespace data when a network namespaces is created or destroyed.
>
> - struct net. The network namespace data structure.
> This structure will grow as variables are made per network
> namespace but this is the minimal starting point.
>
> - Functions to grab a reference to the network namespace.
> I provide both get/put functions that keep a network namespace
> from being freed. And hold/release functions serve as weak references
> and will warn if their count is not zero when the data structure
> is freed. Useful for dealing with more complicated data structures
> like the ipv4 route cache.
>
> - A list of all of the network namespaces so we can iterate over them.
>
> - A slab for the network namespace data structure allowing leaks
> to be spotted.
If I understand this correctly, the only way to get to a namespace is
via get_net_ns_by_pid(), which contains the rcu_read_lock() that matches
the rcu_barrier() below.
So, is the get_net() in sock_copy() in this patch adding a reference to
an element that is guaranteed to already have at least one reference?
If not, how are we preventing sock_copy() from running concurrently with
cleanup_net()? Ah, I see -- in sock_copy() we are getting a reference
to the new struct sock that no one else can get a reference to, so OK.
Ditto for the get_net() in sk_alloc().
But I still don't understand what is protecting the get_net() in
dev_seq_open(). Is there an existing reference? If so, how do we know
that it won't be removed just as we are trying to add our reference
(while at the same time cleanup_net() is running)? Ditto for the other
_open() operations in the same patch. And for netlink_seq_open().
Enlightenment?
Thanx, Paul
> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
> ---
> include/net/net_namespace.h | 68 ++++++++++
> net/core/Makefile | 2 +-
> net/core/net_namespace.c | 292 +++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 361 insertions(+), 1 deletions(-)
> create mode 100644 include/net/net_namespace.h
> create mode 100644 net/core/net_namespace.c
>
> diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
> new file mode 100644
> index 0000000..6344b77
> --- /dev/null
> +++ b/include/net/net_namespace.h
> @@ -0,0 +1,68 @@
> +/*
> + * Operations on the network namespace
> + */
> +#ifndef __NET_NET_NAMESPACE_H
> +#define __NET_NET_NAMESPACE_H
> +
> +#include <asm/atomic.h>
> +#include <linux/workqueue.h>
> +#include <linux/list.h>
> +
> +struct net {
> + atomic_t count; /* To decided when the network
> + * namespace should be freed.
> + */
> + atomic_t use_count; /* To track references we
> + * destroy on demand
> + */
> + struct list_head list; /* list of network namespaces */
> + struct work_struct work; /* work struct for freeing */
> +};
> +
> +extern struct net init_net;
> +extern struct list_head net_namespace_list;
> +
> +extern void __put_net(struct net *net);
> +
> +static inline struct net *get_net(struct net *net)
> +{
> + atomic_inc(&net->count);
> + return net;
> +}
> +
> +static inline void put_net(struct net *net)
> +{
> + if (atomic_dec_and_test(&net->count))
> + __put_net(net);
> +}
> +
> +static inline struct net *hold_net(struct net *net)
> +{
> + atomic_inc(&net->use_count);
> + return net;
> +}
> +
> +static inline void release_net(struct net *net)
> +{
> + atomic_dec(&net->use_count);
> +}
> +
> +extern void net_lock(void);
> +extern void net_unlock(void);
> +
> +#define for_each_net(VAR) \
> + list_for_each_entry(VAR, &net_namespace_list, list)
> +
> +
> +struct pernet_operations {
> + struct list_head list;
> + int (*init)(struct net *net);
> + void (*exit)(struct net *net);
> +};
> +
> +extern int register_pernet_subsys(struct pernet_operations *);
> +extern void unregister_pernet_subsys(struct pernet_operations *);
> +extern int register_pernet_device(struct pernet_operations *);
> +extern void unregister_pernet_device(struct pernet_operations *);
> +
> +#endif /* __NET_NET_NAMESPACE_H */
> diff --git a/net/core/Makefile b/net/core/Makefile
> index 4751613..ea9b3f3 100644
> --- a/net/core/Makefile
> +++ b/net/core/Makefile
> @@ -3,7 +3,7 @@
> #
>
> obj-y := sock.o request_sock.o skbuff.o iovec.o datagram.o stream.o scm.o \
> - gen_stats.o gen_estimator.o
> + gen_stats.o gen_estimator.o net_namespace.o
>
> obj-$(CONFIG_SYSCTL) += sysctl_net_core.o
>
> diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
> new file mode 100644
> index 0000000..f259a9b
> --- /dev/null
> +++ b/net/core/net_namespace.c
> @@ -0,0 +1,292 @@
> +#include <linux/workqueue.h>
> +#include <linux/rtnetlink.h>
> +#include <linux/cache.h>
> +#include <linux/slab.h>
> +#include <linux/list.h>
> +#include <linux/delay.h>
> +#include <net/net_namespace.h>
> +
> +/*
> + * Our network namespace constructor/destructor lists
> + */
> +
> +static LIST_HEAD(pernet_list);
> +static struct list_head *first_device = &pernet_list;
> +static DEFINE_MUTEX(net_mutex);
> +
> +static DEFINE_MUTEX(net_list_mutex);
> +LIST_HEAD(net_namespace_list);
> +
> +static struct kmem_cache *net_cachep;
> +
> +struct net init_net;
> +EXPORT_SYMBOL_GPL(init_net);
> +
> +void net_lock(void)
> +{
> + mutex_lock(&net_list_mutex);
> +}
> +
> +void net_unlock(void)
> +{
> + mutex_unlock(&net_list_mutex);
> +}
> +
> +static struct net *net_alloc(void)
> +{
> + return kmem_cache_alloc(net_cachep, GFP_KERNEL);
> +}
> +
> +static void net_free(struct net *net)
> +{
> + if (!net)
> + return;
> +
> + if (unlikely(atomic_read(&net->use_count) != 0)) {
> + printk(KERN_EMERG "network namespace not free! Usage: %d\n",
> + atomic_read(&net->use_count));
> + return;
> + }
> +
> + kmem_cache_free(net_cachep, net);
> +}
> +
> +static void cleanup_net(struct work_struct *work)
> +{
> + struct pernet_operations *ops;
> + struct list_head *ptr;
> + struct net *net;
> +
> + net = container_of(work, struct net, work);
> +
> + mutex_lock(&net_mutex);
> +
> + /* Don't let anyone else find us. */
> + net_lock();
> + list_del(&net->list);
> + net_unlock();
> +
> + /* Run all of the network namespace exit methods */
> + list_for_each_prev(ptr, &pernet_list) {
> + ops = list_entry(ptr, struct pernet_operations, list);
> + if (ops->exit)
> + ops->exit(net);
> + }
> +
> + mutex_unlock(&net_mutex);
> +
> + /* Ensure there are no outstanding rcu callbacks using this
> + * network namespace.
> + */
> + rcu_barrier();
> +
> + /* Finally it is safe to free my network namespace structure */
> + net_free(net);
> +}
> +
> +
> +void __put_net(struct net *net)
> +{
> + /* Cleanup the network namespace in process context */
> + INIT_WORK(&net->work, cleanup_net);
> + schedule_work(&net->work);
> +}
> +EXPORT_SYMBOL_GPL(__put_net);
> +
> +/*
> + * setup_net runs the initializers for the network namespace object.
> + */
> +static int setup_net(struct net *net)
> +{
> + /* Must be called with net_mutex held */
> + struct pernet_operations *ops;
> + struct list_head *ptr;
> + int error;
> +
> + memset(net, 0, sizeof(struct net));
> + atomic_set(&net->count, 1);
> + atomic_set(&net->use_count, 0);
> +
> + error = 0;
> + list_for_each(ptr, &pernet_list) {
> + ops = list_entry(ptr, struct pernet_operations, list);
> + if (ops->init) {
> + error = ops->init(net);
> + if (error < 0)
> + goto out_undo;
> + }
> + }
> +out:
> + return error;
> +out_undo:
> + /* Walk through the list backwards calling the exit functions
> + * for the pernet modules whose init functions did not fail.
> + */
> + for (ptr = ptr->prev; ptr != &pernet_list; ptr = ptr->prev) {
> + ops = list_entry(ptr, struct pernet_operations, list);
> + if (ops->exit)
> + ops->exit(net);
> + }
> + goto out;
> +}
> +
> +static int __init net_ns_init(void)
> +{
> + int err;
> +
> + printk(KERN_INFO "net_namespace: %zd bytes\n", sizeof(struct net));
> + net_cachep = kmem_cache_create("net_namespace", sizeof(struct net),
> + SMP_CACHE_BYTES,
> + SLAB_PANIC, NULL);
> + mutex_lock(&net_mutex);
> + err = setup_net(&init_net);
> +
> + net_lock();
> + list_add_tail(&init_net.list, &net_namespace_list);
> + net_unlock();
> +
> + mutex_unlock(&net_mutex);
> + if (err)
> + panic("Could not setup the initial network namespace");
> +
> + return 0;
> +}
> +
> +pure_initcall(net_ns_init);
> +
> +static int register_pernet_operations(struct list_head *list,
> + struct pernet_operations *ops)
> +{
> + struct net *net, *undo_net;
> + int error;
> +
> + error = 0;
> + list_add_tail(&ops->list, list);
> + for_each_net(net) {
> + if (ops->init) {
> + error
...
|
|
|
Re: [PATCH 03/16] net: Basic network namespace infrastructure. [message #19985 is a reply to message #19984] |
Sun, 09 September 2007 10:04 |
ebiederm
Messages: 1354 Registered: February 2006
|
Senior Member |
|
|
"Paul E. McKenney" <paulmck@linux.vnet.ibm.com> writes:
> On Sat, Sep 08, 2007 at 03:15:34PM -0600, Eric W. Biederman wrote:
>>
>> This is the basic infrastructure needed to support network
>> namespaces. This infrastructure is:
>> - Registration functions to support initializing per network
>> namespace data when a network namespaces is created or destroyed.
>>
>> - struct net. The network namespace data structure.
>> This structure will grow as variables are made per network
>> namespace but this is the minimal starting point.
>>
>> - Functions to grab a reference to the network namespace.
>> I provide both get/put functions that keep a network namespace
>> from being freed. And hold/release functions serve as weak references
>> and will warn if their count is not zero when the data structure
>> is freed. Useful for dealing with more complicated data structures
>> like the ipv4 route cache.
>>
>> - A list of all of the network namespaces so we can iterate over them.
>>
>> - A slab for the network namespace data structure allowing leaks
>> to be spotted.
>
> If I understand this correctly, the only way to get to a namespace is
> via get_net_ns_by_pid(), which contains the rcu_read_lock() that matches
> the rcu_barrier() below.
Not quite. That is the convoluted case for getting a namespace someone
else is using. current->nsproxy->net_ns works and should require no
locking to read (only the current process may modify it) and does hold
a reference to the network namespace. Similarly for sock->sk_net.
> So, is the get_net() in sock_copy() in this patch adding a reference to
> an element that is guaranteed to already have at least one reference?
Yes.
> If not, how are we preventing sock_copy() from running concurrently with
> cleanup_net()? Ah, I see -- in sock_copy() we are getting a reference
> to the new struct sock that no one else can get a reference to, so OK.
> Ditto for the get_net() in sk_alloc().
> But I still don't understand what is protecting the get_net() in
> dev_seq_open(). Is there an existing reference?
Sort of. The directories under /proc/net are created when create
a network namespace and they are destroyed when the network namespace
is removed. And those directories remember which network namespace
they are for and that is what dev_seq_open is referencing.
So the tricky case what happens if we open a directory under /proc/net
as we are cleaning up a network namespace.
> If so, how do we know
> that it won't be removed just as we are trying to add our reference
> (while at the same time cleanup_net() is running)? Ditto for the other
> _open() operations in the same patch. And for netlink_seq_open().
>
> Enlightenment?
Good spotting. It looks like you have found a legitimate race. Grr.
I thought I had a reference to the network namespace there. I need to
step back and think about this a bit, and see if I can come up with a
legitimate idiom.
I know the network namespace exists and I have not finished
cleanup_net because I can still get to the /proc entries.
I know I cannot use get_net for the reference in in /proc because
otherwise I could not release the network namespace unless I was to
unmount the filesystem, which is not a desirable property.
I think I can change the idiom to:
struct net *maybe_get_net(struct net *net)
{
if (!atomic_inc_not_zero(&net->count))
net = NULL;
return net;
}
Which would make dev_seq_open be:
static int dev_seq_open(struct inode *inode, struct file *file)
{
struct seq_file *seq;
int res;
res = seq_open(file, &dev_seq_ops);
if (!res) {
seq = file->private_data;
seq->private = maybe_get_net(PROC_NET(inode));
if (!seq->private) {
res = -ENOENT;
seq_release(inode, file);
}
}
return res;
}
I'm still asking myself if I need any kind of locking to ensure
struct net does not go away in the mean time, if so rcu_read_lock()
should be sufficient.
I will read through the generic proc code very carefully after
I have slept and see if there is what I the code above is sufficient,
and if so update the patchset.
Eric
_______________________________________________
Containers mailing list
Containers@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/containers
|
|
|
|
Re: [PATCH 03/16] net: Basic network namespace infrastructure. [message #19987 is a reply to message #19985] |
Sun, 09 September 2007 16:45 |
paulmck
Messages: 13 Registered: August 2006
|
Junior Member |
|
|
On Sun, Sep 09, 2007 at 04:04:45AM -0600, Eric W. Biederman wrote:
> "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> writes:
>
> > On Sat, Sep 08, 2007 at 03:15:34PM -0600, Eric W. Biederman wrote:
> >>
> >> This is the basic infrastructure needed to support network
> >> namespaces. This infrastructure is:
> >> - Registration functions to support initializing per network
> >> namespace data when a network namespaces is created or destroyed.
> >>
> >> - struct net. The network namespace data structure.
> >> This structure will grow as variables are made per network
> >> namespace but this is the minimal starting point.
> >>
> >> - Functions to grab a reference to the network namespace.
> >> I provide both get/put functions that keep a network namespace
> >> from being freed. And hold/release functions serve as weak references
> >> and will warn if their count is not zero when the data structure
> >> is freed. Useful for dealing with more complicated data structures
> >> like the ipv4 route cache.
> >>
> >> - A list of all of the network namespaces so we can iterate over them.
> >>
> >> - A slab for the network namespace data structure allowing leaks
> >> to be spotted.
> >
> > If I understand this correctly, the only way to get to a namespace is
> > via get_net_ns_by_pid(), which contains the rcu_read_lock() that matches
> > the rcu_barrier() below.
>
> Not quite. That is the convoluted case for getting a namespace someone
> else is using. current->nsproxy->net_ns works and should require no
> locking to read (only the current process may modify it) and does hold
> a reference to the network namespace. Similarly for sock->sk_net.
Ah! Got it, thank you for the explanation.
> > So, is the get_net() in sock_copy() in this patch adding a reference to
> > an element that is guaranteed to already have at least one reference?
>
> Yes.
>
> > If not, how are we preventing sock_copy() from running concurrently with
> > cleanup_net()? Ah, I see -- in sock_copy() we are getting a reference
> > to the new struct sock that no one else can get a reference to, so OK.
> > Ditto for the get_net() in sk_alloc().
>
> > But I still don't understand what is protecting the get_net() in
> > dev_seq_open(). Is there an existing reference?
>
> Sort of. The directories under /proc/net are created when create
> a network namespace and they are destroyed when the network namespace
> is removed. And those directories remember which network namespace
> they are for and that is what dev_seq_open is referencing.
>
> So the tricky case what happens if we open a directory under /proc/net
> as we are cleaning up a network namespace.
Yep! ;-)
> > If so, how do we know
> > that it won't be removed just as we are trying to add our reference
> > (while at the same time cleanup_net() is running)? Ditto for the other
> > _open() operations in the same patch. And for netlink_seq_open().
> >
> > Enlightenment?
>
> Good spotting. It looks like you have found a legitimate race. Grr.
> I thought I had a reference to the network namespace there. I need to
> step back and think about this a bit, and see if I can come up with a
> legitimate idiom.
>
> I know the network namespace exists and I have not finished
> cleanup_net because I can still get to the /proc entries.
OK. Hmmm... I need to go review locking for /proc...
> I know I cannot use get_net for the reference in in /proc because
> otherwise I could not release the network namespace unless I was to
> unmount the filesystem, which is not a desirable property.
>
> I think I can change the idiom to:
>
> struct net *maybe_get_net(struct net *net)
> {
> if (!atomic_inc_not_zero(&net->count))
> net = NULL;
> return net;
> }
>
> Which would make dev_seq_open be:
>
> static int dev_seq_open(struct inode *inode, struct file *file)
> {
> struct seq_file *seq;
> int res;
> res = seq_open(file, &dev_seq_ops);
> if (!res) {
> seq = file->private_data;
> seq->private = maybe_get_net(PROC_NET(inode));
> if (!seq->private) {
> res = -ENOENT;
> seq_release(inode, file);
> }
> }
> return res;
> }
>
> I'm still asking myself if I need any kind of locking to ensure
> struct net does not go away in the mean time, if so rcu_read_lock()
> should be sufficient.
Agreed -- and it might be possible to leverage the existing locking
in the /proc code.
Thanx, Paul
> I will read through the generic proc code very carefully after
> I have slept and see if there is what I the code above is sufficient,
> and if so update the patchset.
>
> Eric
_______________________________________________
Containers mailing list
Containers@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/containers
|
|
|
|
|
|
|
|
|
|
|
Re: [PATCH 16/16] net: netlink support for moving devices between network namespaces. [message #20008 is a reply to message #19982] |
Mon, 10 September 2007 19:07 |
serue
Messages: 750 Registered: February 2006
|
Senior Member |
|
|
Quoting Eric W. Biederman (ebiederm@xmission.com):
>
> The simplest thing to implement is moving network devices between
> namespaces. However with the same attribute IFLA_NET_NS_PID we can
> easily implement creating devices in the destination network
> namespace as well. However that is a little bit trickier so this
> patch sticks to what is simple and easy.
>
> A pid is used to identify a process that happens to be a member
> of the network namespace we want to move the network device to.
>
> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
> ---
> include/linux/if_link.h | 1 +
> net/core/rtnetlink.c | 35 +++++++++++++++++++++++++++++++++++
> 2 files changed, 36 insertions(+), 0 deletions(-)
>
> diff --git a/include/linux/if_link.h b/include/linux/if_link.h
> index 422084d..84c3492 100644
> --- a/include/linux/if_link.h
> +++ b/include/linux/if_link.h
> @@ -78,6 +78,7 @@ enum
> IFLA_LINKMODE,
> IFLA_LINKINFO,
> #define IFLA_LINKINFO IFLA_LINKINFO
> + IFLA_NET_NS_PID,
> __IFLA_MAX
> };
>
> diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
> index 44f91bb..1b9c32d 100644
> --- a/net/core/rtnetlink.c
> +++ b/net/core/rtnetlink.c
> @@ -35,6 +35,7 @@
> #include <linux/security.h>
> #include <linux/mutex.h>
> #include <linux/if_addr.h>
> +#include <linux/nsproxy.h>
>
> #include <asm/uaccess.h>
> #include <asm/system.h>
> @@ -727,6 +728,7 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = {
> [IFLA_WEIGHT] = { .type = NLA_U32 },
> [IFLA_OPERSTATE] = { .type = NLA_U8 },
> [IFLA_LINKMODE] = { .type = NLA_U8 },
> + [IFLA_NET_NS_PID] = { .type = NLA_U32 },
> };
>
> static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
> @@ -734,12 +736,45 @@ static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
> [IFLA_INFO_DATA] = { .type = NLA_NESTED },
> };
>
> +static struct net *get_net_ns_by_pid(pid_t pid)
> +{
> + struct task_struct *tsk;
> + struct net *net;
> +
> + /* Lookup the network namespace */
> + net = ERR_PTR(-ESRCH);
> + rcu_read_lock();
> + tsk = find_task_by_pid(pid);
> + if (tsk) {
> + task_lock(tsk);
> + if (tsk->nsproxy)
> + net = get_net(tsk->nsproxy->net_ns);
> + task_unlock(tsk);
Thinking... Ok, I'm not sure this is 100% safe in the target tree, but
the long-term correct way probably isn't yet implemented in the net-
tree. Eventually you will want to:
net_ns = NULL;
rcu_read_lock();
tsk = find_task_by_pid(); /* or _pidns equiv? */
nsproxy = task_nsproxy(tsk);
if (nsproxy)
net_ns = get_net(nsproxy->net_ns);
rcu_read_unlock;
What you have here is probably unsafe if tsk is the last task pointing
to it's nsproxy and it does an unshare, bc unshare isn't protected by
task_lock, and you're not rcu_dereferencing tsk->nsproxy (which
task_nsproxy does). At one point we floated a patch to reuse the same
nsproxy in that case which would prevent you having to worry about it,
but that isn't being done in -mm now so i doubt it's in -net.
> + }
> + rcu_read_unlock();
> + return net;
> +}
> +
> static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
> struct nlattr **tb, char *ifname, int modified)
> {
> int send_addr_notify = 0;
> int err;
>
> + if (tb[IFLA_NET_NS_PID]) {
> + struct net *net;
> + net = get_net_ns_by_pid(nla_get_u32(tb[IFLA_NET_NS_PID]));
> + if (IS_ERR(net)) {
> + err = PTR_ERR(net);
> + goto errout;
> + }
> + err = dev_change_net_namespace(dev, net, ifname);
> + put_net(net);
> + if (err)
> + goto errout;
> + modified = 1;
> + }
> +
> if (tb[IFLA_MAP]) {
> struct rtnl_link_ifmap *u_map;
> struct ifmap k_map;
> --
> 1.5.3.rc6.17.g1911
>
> _______________________________________________
> Containers mailing list
> Containers@lists.linux-foundation.org
> https://lists.linux-foundation.org/mailman/listinfo/containers
_______________________________________________
Containers mailing list
Containers@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/containers
|
|
|
Re: [PATCH 03/16] net: Basic network namespace infrastructure. [message #20015 is a reply to message #19969] |
Mon, 10 September 2007 13:16 |
Pavel Emelianov
Messages: 1149 Registered: September 2006
|
Senior Member |
|
|
Eric W. Biederman wrote:
[snip]
> --- /dev/null
> +++ b/include/net/net_namespace.h
> @@ -0,0 +1,68 @@
> +/*
> + * Operations on the network namespace
> + */
> +#ifndef __NET_NET_NAMESPACE_H
> +#define __NET_NET_NAMESPACE_H
> +
> +#include <asm/atomic.h>
> +#include <linux/workqueue.h>
> +#include <linux/list.h>
> +
> +struct net {
Isn't this name is too generic? Why not net_namespace?
> + atomic_t count; /* To decided when the network
> + * namespace should be freed.
> + */
> + atomic_t use_count; /* To track references we
> + * destroy on demand
> + */
> + struct list_head list; /* list of network namespaces */
> + struct work_struct work; /* work struct for freeing */
> +};
[snip]
> --- /dev/null
> +++ b/net/core/net_namespace.c
[snip]
> +static int setup_net(struct net *net)
> +{
> + /* Must be called with net_mutex held */
> + struct pernet_operations *ops;
> + struct list_head *ptr;
> + int error;
> +
> + memset(net, 0, sizeof(struct net));
> + atomic_set(&net->count, 1);
> + atomic_set(&net->use_count, 0);
> +
> + error = 0;
> + list_for_each(ptr, &pernet_list) {
> + ops = list_entry(ptr, struct pernet_operations, list);
> + if (ops->init) {
> + error = ops->init(net);
> + if (error < 0)
> + goto out_undo;
> + }
> + }
> +out:
> + return error;
> +out_undo:
> + /* Walk through the list backwards calling the exit functions
> + * for the pernet modules whose init functions did not fail.
> + */
> + for (ptr = ptr->prev; ptr != &pernet_list; ptr = ptr->prev) {
Good reason for adding list_for_each_continue_reverse :)
> + ops = list_entry(ptr, struct pernet_operations, list);
> + if (ops->exit)
> + ops->exit(net);
> + }
> + goto out;
> +}
> +
> +static int __init net_ns_init(void)
> +{
> + int err;
> +
> + printk(KERN_INFO "net_namespace: %zd bytes\n", sizeof(struct net));
> + net_cachep = kmem_cache_create("net_namespace", sizeof(struct net),
> + SMP_CACHE_BYTES,
> + SLAB_PANIC, NULL);
> + mutex_lock(&net_mutex);
> + err = setup_net(&init_net);
> +
> + net_lock();
> + list_add_tail(&init_net.list, &net_namespace_list);
> + net_unlock();
> +
> + mutex_unlock(&net_mutex);
> + if (err)
> + panic("Could not setup the initial network namespace");
> +
> + return 0;
> +}
> +
> +pure_initcall(net_ns_init);
> +
> +static int register_pernet_operations(struct list_head *list,
> + struct pernet_operations *ops)
> +{
> + struct net *net, *undo_net;
> + int error;
> +
> + error = 0;
> + list_add_tail(&ops->list, list);
> + for_each_net(net) {
> + if (ops->init) {
Maybe it's better to do it vice-versa?
if (ops->init)
for_each_net(net)
ops->init(net);
...
> + error = ops->init(net);
> + if (error)
> + goto out_undo;
> + }
> + }
> +out:
> + return error;
> +
> +out_undo:
> + /* If I have an error cleanup all namespaces I initialized */
> + list_del(&ops->list);
> + for_each_net(undo_net) {
> + if (undo_net == net)
> + goto undone;
> + if (ops->exit)
> + ops->exit(undo_net);
> + }
> +undone:
> + goto out;
> +}
> +
> +static void unregister_pernet_operations(struct pernet_operations *ops)
> +{
> + struct net *net;
> +
> + list_del(&ops->list);
> + for_each_net(net)
> + if (ops->exit)
The same here.
> + ops->exit(net);
> +}
> +
> +/**
> + * register_pernet_subsys - register a network namespace subsystem
> + * @ops: pernet operations structure for the subsystem
> + *
> + * Register a subsystem which has init and exit functions
> + * that are called when network namespaces are created and
> + * destroyed respectively.
> + *
> + * When registered all network namespace init functions are
> + * called for every existing network namespace. Allowing kernel
> + * modules to have a race free view of the set of network namespaces.
> + *
> + * When a new network namespace is created all of the init
> + * methods are called in the order in which they were registered.
> + *
> + * When a network namespace is destroyed all of the exit methods
> + * are called in the reverse of the order with which they were
> + * registered.
> + */
> +int register_pernet_subsys(struct pernet_operations *ops)
> +{
> + int error;
> + mutex_lock(&net_mutex);
> + error = register_pernet_operations(first_device, ops);
> + mutex_unlock(&net_mutex);
> + return error;
> +}
> +EXPORT_SYMBOL_GPL(register_pernet_subsys);
> +
> +/**
> + * unregister_pernet_subsys - unregister a network namespace subsystem
> + * @ops: pernet operations structure to manipulate
> + *
> + * Remove the pernet operations structure from the list to be
> + * used when network namespaces are created or destoryed. In
> + * addition run the exit method for all existing network
> + * namespaces.
> + */
> +void unregister_pernet_subsys(struct pernet_operations *module)
> +{
> + mutex_lock(&net_mutex);
> + unregister_pernet_operations(module);
> + mutex_unlock(&net_mutex);
> +}
> +EXPORT_SYMBOL_GPL(unregister_pernet_subsys);
> +
> +/**
> + * register_pernet_device - register a network namespace device
> + * @ops: pernet operations structure for the subsystem
> + *
> + * Register a device which has init and exit functions
> + * that are called when network namespaces are created and
> + * destroyed respectively.
> + *
> + * When registered all network namespace init functions are
> + * called for every existing network namespace. Allowing kernel
> + * modules to have a race free view of the set of network namespaces.
> + *
> + * When a new network namespace is created all of the init
> + * methods are called in the order in which they were registered.
> + *
> + * When a network namespace is destroyed all of the exit methods
> + * are called in the reverse of the order with which they were
> + * registered.
> + */
> +int register_pernet_device(struct pernet_operations *ops)
> +{
> + int error;
> + mutex_lock(&net_mutex);
> + error = register_pernet_operations(&pernet_list, ops);
> + if (!error && (first_device == &pernet_list))
Very minor: why do you give the name "device" to some pernet_operations?
Thanks,
Pavel
_______________________________________________
Containers mailing list
Containers@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/containers
|
|
|
|
|
|
|
|
|
|
|
Goto Forum:
Current Time: Sun Oct 13 10:30:24 GMT 2024
Total time taken to generate the page: 0.12155 seconds
|