Skip to contentSkip to conversation

mqueue namespace: add struct mq_namespace

RFC PATCH In review Dave Hansen 2 participants 6 messages Jul 10, 2008 VFS

lore
Share & tools
lore
#0 lore raw

RFC PATCH 1/5 mqueue namespace: add struct mq_namespace

From: Cedric Le Goater <clg-NmTC/[email protected]>

This patch adds a struct mq_namespace holding the common attributes of the mqueue namespace.

The current code is modified to use the default mqueue namespace object 'init_mq_ns' and to prepare the ground for futur dynamic objects.

A new option CONFIG_MQ_NS protects configuration not using namespaces.

---

 linux-2.6.git-dave/include/linux/mq_namespace.h |   67 ++++++++++++++
 linux-2.6.git-dave/init/Kconfig                 |    9 +
 linux-2.6.git-dave/ipc/Makefile                 |    1 
 linux-2.6.git-dave/ipc/mq_namespace.c           |   23 +++++
 linux-2.6.git-dave/ipc/mqueue.c                 |  109 ++++++++++++------------
 5 files changed, 158 insertions(+), 51 deletions(-)
include/linux/mq_namespace.h new file +67 -0
diff -puN /dev/null include/linux/mq_namespace.h
@@ -0,0 +1,67 @@
+#ifndef _LINUX_MQ_NAMESPACE_H
+#define _LINUX_MQ_NAMESPACE_H
+
+#include <linux/kref.h>
+
+struct vfsmount;
+
+struct mq_namespace {
+	struct kref	kref;
+	struct vfsmount *mnt;
+
+	unsigned int	queues_count;
+	unsigned int	queues_max;
+	unsigned int	msg_max;
+	unsigned int	msgsize_max;
+};
+
+extern struct mq_namespace init_mq_ns;
+
+/* default values */
+#define DFLT_QUEUESMAX	256	/* max number of message queues */
+#define DFLT_MSGMAX 	10	/* max number of messages in each queue */
+#define HARD_MSGMAX 	(131072/sizeof(void *))
+#define DFLT_MSGSIZEMAX 8192	/* max message size */
+
+#ifdef CONFIG_POSIX_MQUEUE
+#define INIT_MQ_NS(ns)		.ns		= &init_mq_ns,
+#else
+#define INIT_MQ_NS(ns)
+#endif
+
+#if defined(CONFIG_POSIX_MQUEUE) && defined(CONFIG_MQ_NS)
+static inline struct mq_namespace *get_mq_ns(struct mq_namespace *ns)
+{
+	if (ns)
+		kref_get(&ns->kref);
+	return ns;
+}
+
+extern struct mq_namespace *copy_mq_ns(unsigned long clone_flags,
+				struct mq_namespace *old_ns);
+extern void free_mq_ns(struct kref *kref);
+
+static inline void put_mq_ns(struct mq_namespace *ns)
+{
+	if (ns)
+		kref_put(&ns->kref, free_mq_ns);
+}
+
+#else
+
+static inline struct mq_namespace *get_mq_ns(struct mq_namespace *ns)
+{
+	return ns;
+}
+
+static inline struct mq_namespace *copy_mq_ns(unsigned long clone_flags,
+					struct mq_namespace *old_ns)
+{
+	return old_ns;
+}
+
+static inline void put_mq_ns(struct mq_namespace *ns) { }
+
+#endif /* CONFIG_POSIX_MQUEUE */
+
+#endif /* _LINUX_MQ_H */
init/Kconfig renamed from init/Kconfig~mq_namespace-add-mq_namespace +9 -0
diff -puN init/Kconfig~mq_namespace-add-mq_namespace init/Kconfig
@@ -493,6 +493,15 @@ config PID_NS
 	  Unless you want to work with an experimental feature
 	  say N here.
 
+config MQ_NS
+       bool "POSIX Message Queues namespace"
+       depends on NAMESPACES && POSIX_MQUEUE
+       help
+	 Support for POSIX Message Queues namespaces. This allows
+	 having different POSIX Message Queues filesystems containing
+	 message queues with the same name. Yet another a building
+	 block of containers.
+
 config BLK_DEV_INITRD
 	bool "Initial RAM filesystem and RAM disk (initramfs/initrd) support"
 	depends on BROKEN || !FRV
ipc/Makefile renamed from ipc/Makefile~mq_namespace-add-mq_namespace +1 -0
diff -puN ipc/Makefile~mq_namespace-add-mq_namespace ipc/Makefile
@@ -8,4 +8,5 @@ obj-$(CONFIG_SYSVIPC_SYSCTL) += ipc_sysc
 obj_mq-$(CONFIG_COMPAT) += compat_mq.o
 obj-$(CONFIG_POSIX_MQUEUE) += mqueue.o msgutil.o $(obj_mq-y)
 obj-$(CONFIG_IPC_NS) += namespace.o
+obj-$(CONFIG_MQ_NS) += mq_namespace.o
 
ipc/mq_namespace.c new file +23 -0
diff -puN /dev/null ipc/mq_namespace.c
@@ -0,0 +1,23 @@
+/*
+ *  Copyright (C) 2007 IBM Corporation
+ *
+ *  Author: Cedric Le Goater <clg-NmTC/[email protected]>
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License as
+ *  published by the Free Software Foundation, version 2 of the
+ *  License.
+ */
+
+#include <linux/mq_namespace.h>
+
+struct mq_namespace *copy_mq_ns(unsigned long clone_flags,
+				struct mq_namespace *old_ns)
+{
+	BUG_ON(!old_ns);
+	return get_mq_ns(old_ns);
+}
+
+void free_mq_ns(struct kref *kref)
+{
+}
ipc/mqueue.c renamed from ipc/mqueue.c~mq_namespace-add-mq_namespace +58 -51

312 lines not on this page · raw message

_

#1 lore raw

RFC PATCH 2/5 mqueue namespace: add unshare support

From: Cedric Le Goater <clg-NmTC/[email protected]>

This patch includes the mqueue namespace in the nsproxy object. It also adds the support of unshare() and clone() with a new clone flag.

It's totally harmless for the moment because the current code still uses the default mqueue namespace object 'init_mq_ns'

Changes since v6 Mar 05, 2008:

* dropped new clone flag CLONE_NEWMQ and used CLONE_NEWIPC instead

Changes since v5 Feb 28, 2008:

* fix typo in create_new_namespaces()

Changes since v4:

* remove CLONE_NEWNS enforcement. stalled user mounts are handled in the fs ops.

---

 linux-2.6.git-dave/include/linux/init_task.h    |    2 +
 linux-2.6.git-dave/include/linux/mq_namespace.h |    1 
 linux-2.6.git-dave/include/linux/nsproxy.h      |    2 +
 linux-2.6.git-dave/ipc/mq_namespace.c           |   36 +++++++++++++++++++++++-
 linux-2.6.git-dave/kernel/nsproxy.c             |   11 +++++++
 5 files changed, 51 insertions(+), 1 deletion(-)
include/linux/init_task.h renamed from include/linux/init_task.h~mq_namespace-add-mq_namespace-to-nsproxy +2 -0
diff -puN include/linux/init_task.h~mq_namespace-add-mq_namespace-to-nsproxy include/linux/init_task.h
@@ -10,6 +10,7 @@
 #include <linux/user_namespace.h>
 #include <linux/securebits.h>
 #include <net/net_namespace.h>
+#include <linux/mq_namespace.h>
 
 extern struct files_struct init_files;
 
@@ -58,6 +59,7 @@ extern struct nsproxy init_nsproxy;
 	INIT_NET_NS(net_ns)                                             \
 	INIT_IPC_NS(ipc_ns)						\
 	.user_ns	= &init_user_ns,				\
+	INIT_MQ_NS(mq_ns)						\
 }
 
 #define INIT_SIGHAND(sighand) {						\
include/linux/mq_namespace.h renamed from include/linux/mq_namespace.h~mq_namespace-add-mq_namespace-to-nsproxy +1 -0
diff -puN include/linux/mq_namespace.h~mq_namespace-add-mq_namespace-to-nsproxy include/linux/mq_namespace.h
@@ -2,6 +2,7 @@
 #define _LINUX_MQ_NAMESPACE_H
 
 #include <linux/kref.h>
+#include <linux/err.h>
 
 struct vfsmount;
 
include/linux/nsproxy.h renamed from include/linux/nsproxy.h~mq_namespace-add-mq_namespace-to-nsproxy +2 -0
diff -puN include/linux/nsproxy.h~mq_namespace-add-mq_namespace-to-nsproxy include/linux/nsproxy.h
@@ -8,6 +8,7 @@ struct mnt_namespace;
 struct uts_namespace;
 struct ipc_namespace;
 struct pid_namespace;
+struct mq_namespace;
 
 /*
  * A structure to contain pointers to all per-process
@@ -29,6 +30,7 @@ struct nsproxy {
 	struct pid_namespace *pid_ns;
 	struct user_namespace *user_ns;
 	struct net 	     *net_ns;
+	struct mq_namespace *mq_ns;
 };
 extern struct nsproxy init_nsproxy;
 
ipc/mq_namespace.c renamed from ipc/mq_namespace.c~mq_namespace-add-mq_namespace-to-nsproxy +35 -1
diff -puN ipc/mq_namespace.c~mq_namespace-add-mq_namespace-to-nsproxy ipc/mq_namespace.c
@@ -10,14 +10,48 @@
  */
 
 #include <linux/mq_namespace.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+
+static struct mq_namespace *clone_mq_ns(struct mq_namespace *old_ns)
+{
+	struct mq_namespace *mq_ns;
+
+	mq_ns = kmalloc(sizeof(struct mq_namespace), GFP_KERNEL);
+	if (!mq_ns)
+		return ERR_PTR(-ENOMEM);
+
+	kref_init(&mq_ns->kref);
+	mq_ns->queues_count	= 0;
+	mq_ns->queues_max	= DFLT_QUEUESMAX;
+	mq_ns->msg_max		= DFLT_MSGMAX;
+	mq_ns->msgsize_max	= DFLT_MSGSIZEMAX;
+	mq_ns->mnt		= NULL;
+	return mq_ns;
+}
 
 struct mq_namespace *copy_mq_ns(unsigned long clone_flags,
 				struct mq_namespace *old_ns)
 {
+	struct mq_namespace *mq_ns;
+
 	BUG_ON(!old_ns);
-	return get_mq_ns(old_ns);
+	get_mq_ns(old_ns);
+
+	if (!(clone_flags & CLONE_NEWIPC))
+		return old_ns;
+
+	mq_ns = clone_mq_ns(old_ns);
+
+	put_mq_ns(old_ns);
+	return mq_ns;
 }
 
 void free_mq_ns(struct kref *kref)
 {
+	struct mq_namespace *ns;
+
+	ns = container_of(kref, struct mq_namespace, kref);
+	kfree(ns);
 }
kernel/nsproxy.c renamed from kernel/nsproxy.c~mq_namespace-add-mq_namespace-to-nsproxy +11 -0
diff -puN kernel/nsproxy.c~mq_namespace-add-mq_namespace-to-nsproxy kernel/nsproxy.c
@@ -93,8 +93,17 @@ static struct nsproxy *create_new_namesp
 		goto out_net;
 	}
 
+	new_nsp->mq_ns = copy_mq_ns(flags, tsk->nsproxy->mq_ns);
+	if (IS_ERR(new_nsp->mq_ns)) {
+		err = PTR_ERR(new_nsp->mq_ns);
+		goto out_mq;
+	}
+
 	return new_nsp;
 
+out_mq:
+	if (new_nsp->net_ns)
+		put_net(new_nsp->net_ns);
 out_net:
 	if (new_nsp->user_ns)
 		put_user_ns(new_nsp->user_ns);
@@ -182,6 +191,8 @@ void free_nsproxy(struct nsproxy *ns)
 		put_pid_ns(ns->pid_ns);
 	if (ns->user_ns)
 		put_user_ns(ns->user_ns);
+	if (ns->mq_ns)
+		put_mq_ns(ns->mq_ns);
 	put_net(ns->net_ns);
 	kmem_cache_free(nsproxy_cachep, ns);
 }

_

#2 lore raw

Re: [RFC][PATCH 2/5] mqueue namespace: add unshare support

"Dave Hansen" <[email protected]>

Quoted 6 lines

From: Cedric Le Goater <clg-NmTC/[email protected]>

This patch includes the mqueue namespace in the nsproxy object. It also adds the support of unshare() and clone() with a new clone flag.

                                                        ^^^
Quoted 7 lines

It's totally harmless for the moment because the current code still uses the default mqueue namespace object 'init_mq_ns'

Changes since v6 Mar 05, 2008:

* dropped new clone flag CLONE_NEWMQ and used CLONE_NEWIPC instead

Maybe the description above should be updated too?

Quoted 53 lines

Changes since v5 Feb 28, 2008:

* fix typo in create_new_namespaces()

Changes since v4:

* remove CLONE_NEWNS enforcement. stalled user mounts are handled in the fs ops.

---

 linux-2.6.git-dave/include/linux/init_task.h    |    2 +
 linux-2.6.git-dave/include/linux/mq_namespace.h |    1
 linux-2.6.git-dave/include/linux/nsproxy.h      |    2 +
 linux-2.6.git-dave/ipc/mq_namespace.c           |   36
+++++++++++++++++++++++-
 linux-2.6.git-dave/kernel/nsproxy.c             |   11 +++++++
 5 files changed, 51 insertions(+), 1 deletion(-)

diff -puN include/linux/init_task.h~mq_namespace-add-mq_namespace-to-nsproxy include/linux/init_task.h
---
linux-2.6.git/include/linux/init_task.h~mq_namespace-add-mq_namespace-to-nsproxy 2008-06-24
12:03:17.000000000 -0700
+++ linux-2.6.git-dave/include/linux/init_task.h 2008-06-24
12:03:17.000000000 -0700

include/linux/init_task.h renamed from include/linux/init_task.h~mq_namespace-add-mq_namespace-to-nsproxy +2 -0
@@ -10,6 +10,7 @@
 #include <linux/user_namespace.h>
 #include <linux/securebits.h>
 #include <net/net_namespace.h>
+#include <linux/mq_namespace.h>
 
 extern struct files_struct init_files;
 
@@ -58,6 +59,7 @@ extern struct nsproxy init_nsproxy;
 	INIT_NET_NS(net_ns)                                             \
 	INIT_IPC_NS(ipc_ns)						\
 	.user_ns	= &init_user_ns,				\
+	INIT_MQ_NS(mq_ns)						\
 }
 
 #define INIT_SIGHAND(sighand) {						\

diff -puN include/linux/mq_namespace.h~mq_namespace-add-mq_namespace-to-nsproxy include/linux/mq_namespace.h
---
linux-2.6.git/include/linux/mq_namespace.h~mq_namespace-add-mq_namespace-to-nsproxy 2008-06-24
12:03:17.000000000 -0700
+++ linux-2.6.git-dave/include/linux/mq_namespace.h 2008-06-24
12:03:17.000000000 -0700

include/linux/mq_namespace.h line 5

Quoted 4 lines
include/linux/mq_namespace.h renamed from include/linux/mq_namespace.h~mq_namespace-add-mq_namespace-to-nsproxy +1 -0
@@ -2,6 +2,7 @@
 #define _LINUX_MQ_NAMESPACE_H
 
 #include <linux/kref.h>
+#include <linux/err.h>

Why is this necessary (in this patch)?

Quoted 117 lines
include/linux/mq_namespace.h renamed from include/linux/mq_namespace.h~mq_namespace-add-mq_namespace-to-nsproxy +0 -0
 struct vfsmount;
 

diff -puN include/linux/nsproxy.h~mq_namespace-add-mq_namespace-to-nsproxy include/linux/nsproxy.h
---
linux-2.6.git/include/linux/nsproxy.h~mq_namespace-add-mq_namespace-to-nsproxy 2008-06-24
12:03:17.000000000 -0700
+++ linux-2.6.git-dave/include/linux/nsproxy.h 2008-06-24
12:03:17.000000000 -0700

include/linux/nsproxy.h renamed from include/linux/nsproxy.h~mq_namespace-add-mq_namespace-to-nsproxy +2 -0
@@ -8,6 +8,7 @@ struct mnt_namespace;
 struct uts_namespace;
 struct ipc_namespace;
 struct pid_namespace;
+struct mq_namespace;
 
 /*
  * A structure to contain pointers to all per-process
@@ -29,6 +30,7 @@ struct nsproxy {
 	struct pid_namespace *pid_ns;
 	struct user_namespace *user_ns;
 	struct net 	     *net_ns;
+	struct mq_namespace *mq_ns;
 };
 extern struct nsproxy init_nsproxy;
 

diff -puN ipc/mq_namespace.c~mq_namespace-add-mq_namespace-to-nsproxy ipc/mq_namespace.c
---
linux-2.6.git/ipc/mq_namespace.c~mq_namespace-add-mq_namespace-to-nsproxy 2008-06-24
12:03:17.000000000 -0700
+++ linux-2.6.git-dave/ipc/mq_namespace.c 2008-06-24 12:03:17.000000000
-0700

ipc/mq_namespace.c renamed from ipc/mq_namespace.c~mq_namespace-add-mq_namespace-to-nsproxy +35 -1
@@ -10,14 +10,48 @@
  */
 
 #include <linux/mq_namespace.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+
+static struct mq_namespace *clone_mq_ns(struct mq_namespace *old_ns)
+{
+	struct mq_namespace *mq_ns;
+
+	mq_ns = kmalloc(sizeof(struct mq_namespace), GFP_KERNEL);
+	if (!mq_ns)
+		return ERR_PTR(-ENOMEM);
+
+	kref_init(&mq_ns->kref);
+	mq_ns->queues_count	= 0;
+	mq_ns->queues_max	= DFLT_QUEUESMAX;
+	mq_ns->msg_max		= DFLT_MSGMAX;
+	mq_ns->msgsize_max	= DFLT_MSGSIZEMAX;
+	mq_ns->mnt		= NULL;
+	return mq_ns;
+}
 
 struct mq_namespace *copy_mq_ns(unsigned long clone_flags,
 				struct mq_namespace *old_ns)
 {
+	struct mq_namespace *mq_ns;
+
 	BUG_ON(!old_ns);
-	return get_mq_ns(old_ns);
+	get_mq_ns(old_ns);
+
+	if (!(clone_flags & CLONE_NEWIPC))
+		return old_ns;
+
+	mq_ns = clone_mq_ns(old_ns);
+
+	put_mq_ns(old_ns);
+	return mq_ns;
 }
 
 void free_mq_ns(struct kref *kref)
 {
+	struct mq_namespace *ns;
+
+	ns = container_of(kref, struct mq_namespace, kref);
+	kfree(ns);
 }

diff -puN kernel/nsproxy.c~mq_namespace-add-mq_namespace-to-nsproxy kernel/nsproxy.c
---
linux-2.6.git/kernel/nsproxy.c~mq_namespace-add-mq_namespace-to-nsproxy 2008-06-24
12:03:17.000000000 -0700
+++ linux-2.6.git-dave/kernel/nsproxy.c 2008-06-24 12:03:17.000000000
-0700

kernel/nsproxy.c renamed from kernel/nsproxy.c~mq_namespace-add-mq_namespace-to-nsproxy +11 -0
@@ -93,8 +93,17 @@ static struct nsproxy *create_new_namesp
 		goto out_net;
 	}
 
+	new_nsp->mq_ns = copy_mq_ns(flags, tsk->nsproxy->mq_ns);
+	if (IS_ERR(new_nsp->mq_ns)) {
+		err = PTR_ERR(new_nsp->mq_ns);
+		goto out_mq;
+	}
+
 	return new_nsp;
 
+out_mq:
+	if (new_nsp->net_ns)
+		put_net(new_nsp->net_ns);
 out_net:
 	if (new_nsp->user_ns)
 		put_user_ns(new_nsp->user_ns);
@@ -182,6 +191,8 @@ void free_nsproxy(struct nsproxy *ns)
 		put_pid_ns(ns->pid_ns);
 	if (ns->user_ns)
 		put_user_ns(ns->user_ns);
+	if (ns->mq_ns)
+		put_mq_ns(ns->mq_ns);
 	put_net(ns->net_ns);
 	kmem_cache_free(nsproxy_cachep, ns);
 }

_

Signature · 1 line
Daniel Hokka Zakrisson
#3 lore raw

RFC PATCH 3/5 fs: add get_sb_single_ns() helper routine

In reply to Dave Hansen

From: Cedric Le Goater <clg-NmTC/[email protected]>

This patch add a helper routine get_sb_single_ns() which allocates a single super_block per instance of namespace. The data parameter is used to differentiate the namespaces.

This is used in subsystems with an internal fs like mqueue.

TODO:
- use in pidns and devpts

---

 linux-2.6.git-dave/fs/super.c         |   37 ++++++++++++++++++++++++++++++++++
 linux-2.6.git-dave/include/linux/fs.h |    4 +++
 2 files changed, 41 insertions(+)
fs/super.c renamed from fs/super.c~add-get_sb_single_ns-helper +37 -0
diff -puN fs/super.c~add-get_sb_single_ns-helper fs/super.c
@@ -882,6 +882,43 @@ int get_sb_single(struct file_system_typ
 
 EXPORT_SYMBOL(get_sb_single);
 
+static int compare_sb_single_ns(struct super_block *sb, void *data)
+{
+	return sb->s_fs_info == data;
+}
+
+static int set_sb_single_ns(struct super_block *sb, void *data)
+{
+	sb->s_fs_info = data;
+	return set_anon_super(sb, data);
+}
+
+int get_sb_single_ns(struct file_system_type *fs_type,
+	int flags, void *data,
+	int (*fill_super)(struct super_block *, void *, int),
+	struct vfsmount *mnt)
+{
+	struct super_block *s;
+	int error;
+
+	s = sget(fs_type, compare_sb_single_ns, set_sb_single_ns, data);
+	if (IS_ERR(s))
+		return PTR_ERR(s);
+	if (!s->s_root) {
+		s->s_flags = flags;
+		error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
+		if (error) {
+			up_write(&s->s_umount);
+			deactivate_super(s);
+			return error;
+		}
+		s->s_flags |= MS_ACTIVE;
+	}
+	do_remount_sb(s, flags, data, 0);
+	return simple_set_mnt(mnt, s);
+}
+EXPORT_SYMBOL(get_sb_single_ns);
+
 struct vfsmount *
 vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)
 {
include/linux/fs.h renamed from include/linux/fs.h~add-get_sb_single_ns-helper +4 -0
diff -puN include/linux/fs.h~add-get_sb_single_ns-helper include/linux/fs.h
@@ -1502,6 +1502,10 @@ extern int get_sb_nodev(struct file_syst
 	int flags, void *data,
 	int (*fill_super)(struct super_block *, void *, int),
 	struct vfsmount *mnt);
+extern int get_sb_single_ns(struct file_system_type *fs_type,
+	int flags, void *data,
+	int (*fill_super)(struct super_block *, void *, int),
+	struct vfsmount *mnt);
 void generic_shutdown_super(struct super_block *sb);
 void kill_block_super(struct super_block *sb);
 void kill_anon_super(struct super_block *sb);

_

#4 lore raw

RFC PATCH 4/5 mqueue namespace: enable the mqueue namespace

In reply to Dave Hansen

From: Cedric Le Goater <clg-NmTC/[email protected]>

Move forward and start using the mqueue namespace.

The single super block mount of the file system is modified to allow one mount per namespace. This is achieved by storing the namespace in the super_block s_fs_info attribute.

Changes since v5 Feb 28, 2008:

* fix race on sb->s_fs_info when the namespace is freed

Changes since v4:

* check mq_ns validity when the message queue is accessed through a user mount and eventually return -EACCES if mq_ns is bogus

---

 linux-2.6.git-dave/include/linux/mq_namespace.h |    2 +
 linux-2.6.git-dave/ipc/mq_namespace.c           |   10 +++++-
 linux-2.6.git-dave/ipc/mqueue.c                 |   37 ++++++++++++++++++------
 3 files changed, 40 insertions(+), 9 deletions(-)
include/linux/mq_namespace.h renamed from include/linux/mq_namespace.h~mq_namespace-use-mq_namespace +2 -0
diff -puN include/linux/mq_namespace.h~mq_namespace-use-mq_namespace include/linux/mq_namespace.h
@@ -3,6 +3,7 @@
 
 #include <linux/kref.h>
 #include <linux/err.h>
+#include <linux/fs.h>
 
 struct vfsmount;
 
@@ -17,6 +18,7 @@ struct mq_namespace {
 };
 
 extern struct mq_namespace init_mq_ns;
+extern struct file_system_type mqueue_fs_type;
 
 /* default values */
 #define DFLT_QUEUESMAX	256	/* max number of message queues */
ipc/mq_namespace.c renamed from ipc/mq_namespace.c~mq_namespace-use-mq_namespace +9 -1
diff -puN ipc/mq_namespace.c~mq_namespace-use-mq_namespace ipc/mq_namespace.c
@@ -13,6 +13,7 @@
 #include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/err.h>
+#include <linux/mount.h>
 
 static struct mq_namespace *clone_mq_ns(struct mq_namespace *old_ns)
 {
@@ -27,7 +28,12 @@ static struct mq_namespace *clone_mq_ns(
 	mq_ns->queues_max	= DFLT_QUEUESMAX;
 	mq_ns->msg_max		= DFLT_MSGMAX;
 	mq_ns->msgsize_max	= DFLT_MSGSIZEMAX;
-	mq_ns->mnt		= NULL;
+	mq_ns->mnt		= kern_mount_data(&mqueue_fs_type, mq_ns);
+	if (IS_ERR(mq_ns->mnt)) {
+		void *error = mq_ns->mnt;
+		kfree(mq_ns);
+		return error;
+	}
 	return mq_ns;
 }
 
@@ -53,5 +59,7 @@ void free_mq_ns(struct kref *kref)
 	struct mq_namespace *ns;
 
 	ns = container_of(kref, struct mq_namespace, kref);
+	ns->mnt->mnt_sb->s_fs_info = NULL;
+	mntput(ns->mnt);
 	kfree(ns);
 }
ipc/mqueue.c renamed from ipc/mqueue.c~mq_namespace-use-mq_namespace +29 -8
diff -puN ipc/mqueue.c~mq_namespace-use-mq_namespace ipc/mqueue.c
@@ -204,7 +204,10 @@ static int mqueue_get_sb(struct file_sys
 			 int flags, const char *dev_name,
 			 void *data, struct vfsmount *mnt)
 {
-	return get_sb_single(fs_type, flags, data, mqueue_fill_super, mnt);
+	if (!(flags & MS_KERNMOUNT))
+		data = current->nsproxy->mq_ns;
+
+	return get_sb_single_ns(fs_type, flags, data, mqueue_fill_super, mnt);
 }
 
 static void init_once(struct kmem_cache *cachep, void *foo)
@@ -235,7 +238,7 @@ static void mqueue_delete_inode(struct i
 	struct user_struct *user;
 	unsigned long mq_bytes;
 	int i;
-	struct mq_namespace *mq_ns = &init_mq_ns;
+	struct mq_namespace *mq_ns = inode->i_sb->s_fs_info;
 
 	if (S_ISDIR(inode->i_mode)) {
 		clear_inode(inode);
@@ -256,7 +259,8 @@ static void mqueue_delete_inode(struct i
 	if (user) {
 		spin_lock(&mq_lock);
 		user->mq_bytes -= mq_bytes;
-		mq_ns->queues_count--;
+		if (mq_ns)
+			mq_ns->queues_count--;
 		spin_unlock(&mq_lock);
 		free_uid(user);
 	}
@@ -268,7 +272,15 @@ static int mqueue_create(struct inode *d
 	struct inode *inode;
 	struct mq_attr *attr = dentry->d_fsdata;
 	int error;
-	struct mq_namespace *mq_ns = &init_mq_ns;
+	struct mq_namespace *mq_ns = dir->i_sb->s_fs_info;
+
+	/*
+	 * There is a race on sb->s_fs_info with free_mq_ns() but it
+	 * shouldn't be an issue as we are only interested in
+	 * current->nsproxy->mq_ns which is valid.
+	 */
+	if (mq_ns != current->nsproxy->mq_ns)
+		return -EACCES;
 
 	spin_lock(&mq_lock);
 	if (mq_ns->queues_count >= mq_ns->queues_max &&
@@ -301,6 +313,15 @@ out_lock:
 static int mqueue_unlink(struct inode *dir, struct dentry *dentry)
 {
   	struct inode *inode = dentry->d_inode;
+	struct mq_namespace *mq_ns = dir->i_sb->s_fs_info;
+
+	/*
+	 * There is a race on sb->s_fs_info with free_mq_ns() but it
+	 * shouldn't be an issue as we are only interested in
+	 * current->nsproxy->mq_ns which is valid.
+	 */
+	if (mq_ns != current->nsproxy->mq_ns)
+		return -EACCES;
 
 	dir->i_ctime = dir->i_mtime = dir->i_atime = CURRENT_TIME;
 	dir->i_size -= DIRENT_SIZE;
@@ -670,7 +691,7 @@ asmlinkage long sys_mq_open(const char _
 	struct file *filp;
 	char *name;
 	int fd, error;
-	struct mq_namespace *mq_ns = &init_mq_ns;
+	struct mq_namespace *mq_ns = current->nsproxy->mq_ns;
 
 	error = audit_mq_open(oflag, mode, u_attr);
 	if (error != 0)
@@ -738,7 +759,7 @@ asmlinkage long sys_mq_unlink(const char
 	char *name;
 	struct dentry *dentry;
 	struct inode *inode = NULL;
-	struct mq_namespace *mq_ns = &init_mq_ns;
+	struct mq_namespace *mq_ns = current->nsproxy->mq_ns;
 
 	name = getname(u_name);
 	if (IS_ERR(name))
@@ -1203,7 +1224,7 @@ static struct super_operations mqueue_su
 	.drop_inode = generic_delete_inode,
 };
 
-static struct file_system_type mqueue_fs_type = {
+struct file_system_type mqueue_fs_type = {
 	.name = "mqueue",
 	.get_sb = mqueue_get_sb,
 	.kill_sb = kill_litter_super,
@@ -1280,7 +1301,7 @@ static int __init init_mqueue_fs(void)
 	if (error)
 		goto out_sysctl;
 
-	init_mq_ns.mnt = kern_mount(&mqueue_fs_type);
+	init_mq_ns.mnt = kern_mount_data(&mqueue_fs_type, &init_mq_ns);
 	if (IS_ERR(init_mq_ns.mnt)) {
 		error = PTR_ERR(init_mq_ns.mnt);
 		goto out_filesystem;

_

#5 lore raw

RFC PATCH 5/5 Subject: mqueue namespace: adapt sysctl

In reply to Dave Hansen

From: Cedric Le Goater <clg-NmTC/[email protected]>

Largely inspired from ipc/ipc_sysctl.c. This patch isolates the mqueue sysctl stuff in its own file.

---

 linux-2.6.git-dave/include/linux/mq_namespace.h |   10 ++
 linux-2.6.git-dave/init/Kconfig                 |    6 +
 linux-2.6.git-dave/ipc/Makefile                 |    1 
 linux-2.6.git-dave/ipc/mq_sysctl.c              |  117 ++++++++++++++++++++++++
 linux-2.6.git-dave/ipc/mqueue.c                 |   56 -----------
 5 files changed, 135 insertions(+), 55 deletions(-)
include/linux/mq_namespace.h renamed from include/linux/mq_namespace.h~mq_namespace-fix-sysctl +10 -0
diff -puN include/linux/mq_namespace.h~mq_namespace-fix-sysctl include/linux/mq_namespace.h
@@ -67,4 +67,14 @@ static inline void put_mq_ns(struct mq_n
 
 #endif /* CONFIG_POSIX_MQUEUE */
 
+#ifdef CONFIG_POSIX_MQUEUE_SYSCTL
+struct ctl_table_header;
+extern struct ctl_table_header *mq_register_sysctl_table(void);
+#else
+static inline struct ctl_table_header *mq_register_sysctl_table(void)
+{
+	return NULL;
+}
+#endif /* CONFIG_POSIX_MQUEUE_SYSCTL */
+
 #endif /* _LINUX_MQ_H */
init/Kconfig renamed from init/Kconfig~mq_namespace-fix-sysctl +6 -0
diff -puN init/Kconfig~mq_namespace-fix-sysctl init/Kconfig
@@ -148,6 +148,12 @@ config POSIX_MQUEUE
 
 	  If unsure, say Y.
 
+config POSIX_MQUEUE_SYSCTL
+	bool
+	depends on POSIX_MQUEUE
+	depends on SYSCTL
+	default y
+
 config BSD_PROCESS_ACCT
 	bool "BSD Process Accounting"
 	help
ipc/Makefile renamed from ipc/Makefile~mq_namespace-fix-sysctl +1 -0
diff -puN ipc/Makefile~mq_namespace-fix-sysctl ipc/Makefile
@@ -9,4 +9,5 @@ obj_mq-$(CONFIG_COMPAT) += compat_mq.o
 obj-$(CONFIG_POSIX_MQUEUE) += mqueue.o msgutil.o $(obj_mq-y)
 obj-$(CONFIG_IPC_NS) += namespace.o
 obj-$(CONFIG_MQ_NS) += mq_namespace.o
+obj-$(CONFIG_POSIX_MQUEUE_SYSCTL) += mq_sysctl.o
 
ipc/mq_sysctl.c new file +117 -0

117 lines not on this page · raw message

ipc/mqueue.c renamed from ipc/mqueue.c~mq_namespace-fix-sysctl +1 -55

68 lines not on this page · raw message

_