proc: Usable inode numbers for the namespace file descriptors.

Assign a unique proc inode to each namespace, and use that
inode number to ensure we only allocate at most one proc
inode for every namespace in proc.

A single proc inode per namespace allows userspace to test
to see if two processes are in the same namespace.

This has been a long requested feature and only blocked because
a naive implementation would put the id in a global space and
would ultimately require having a namespace for the names of
namespaces, making migration and certain virtualization tricks
impossible.

We still don't have per superblock inode numbers for proc, which
appears necessary for application unaware checkpoint/restart and
migrations (if the application is using namespace file descriptors)
but that is now allowd by the design if it becomes important.

I have preallocated the ipc and uts initial proc inode numbers so
their structures can be statically initialized.

Signed-off-by: Eric W. Biederman <[email protected]>
This commit is contained in:
Eric W. Biederman 2011-06-15 10:21:48 -07:00
commit 98f842e675
18 changed files with 132 additions and 12 deletions

View file

@ -16,6 +16,7 @@
#include <linux/msg.h>
#include <linux/ipc_namespace.h>
#include <linux/utsname.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#include "util.h"
@ -30,6 +31,7 @@ DEFINE_SPINLOCK(mq_lock);
struct ipc_namespace init_ipc_ns = {
.count = ATOMIC_INIT(1),
.user_ns = &init_user_ns,
.proc_inum = PROC_IPC_INIT_INO,
};
atomic_t nr_ipc_ns = ATOMIC_INIT(1);

View file

@ -26,9 +26,16 @@ static struct ipc_namespace *create_ipc_ns(struct user_namespace *user_ns,
if (ns == NULL)
return ERR_PTR(-ENOMEM);
err = proc_alloc_inum(&ns->proc_inum);
if (err) {
kfree(ns);
return ERR_PTR(err);
}
atomic_set(&ns->count, 1);
err = mq_init_ns(ns);
if (err) {
proc_free_inum(ns->proc_inum);
kfree(ns);
return ERR_PTR(err);
}
@ -111,6 +118,7 @@ static void free_ipc_ns(struct ipc_namespace *ns)
*/
ipcns_notify(IPCNS_REMOVED);
put_user_ns(ns->user_ns);
proc_free_inum(ns->proc_inum);
kfree(ns);
}
@ -172,10 +180,18 @@ static int ipcns_install(struct nsproxy *nsproxy, void *new)
return 0;
}
static unsigned int ipcns_inum(void *vp)
{
struct ipc_namespace *ns = vp;
return ns->proc_inum;
}
const struct proc_ns_operations ipcns_operations = {
.name = "ipc",
.type = CLONE_NEWIPC,
.get = ipcns_get,
.put = ipcns_put,
.install = ipcns_install,
.inum = ipcns_inum,
};