Commit 614b84cf authored by Serge E. Hallyn's avatar Serge E. Hallyn Committed by Linus Torvalds

namespaces: mqueue ns: move mqueue_mnt into struct ipc_namespace

Move mqueue vfsmount plus a few tunables into the ipc_namespace struct.
The CONFIG_IPC_NS boolean and the ipc_namespace struct will serve both the
posix message queue namespaces and the SYSV ipc namespaces.

The sysctl code will be fixed separately in patch 3.  After just this
patch, making a change to posix mqueue tunables always changes the values
in the initial ipc namespace.
Signed-off-by: default avatarCedric Le Goater <clg@fr.ibm.com>
Signed-off-by: default avatarSerge E. Hallyn <serue@us.ibm.com>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 909e6d94
...@@ -44,24 +44,55 @@ struct ipc_namespace { ...@@ -44,24 +44,55 @@ struct ipc_namespace {
int shm_tot; int shm_tot;
struct notifier_block ipcns_nb; struct notifier_block ipcns_nb;
/* The kern_mount of the mqueuefs sb. We take a ref on it */
struct vfsmount *mq_mnt;
/* # queues in this ns, protected by mq_lock */
unsigned int mq_queues_count;
/* next fields are set through sysctl */
unsigned int mq_queues_max; /* initialized to DFLT_QUEUESMAX */
unsigned int mq_msg_max; /* initialized to DFLT_MSGMAX */
unsigned int mq_msgsize_max; /* initialized to DFLT_MSGSIZEMAX */
}; };
extern struct ipc_namespace init_ipc_ns; extern struct ipc_namespace init_ipc_ns;
extern atomic_t nr_ipc_ns; extern atomic_t nr_ipc_ns;
#ifdef CONFIG_SYSVIPC #if defined(CONFIG_POSIX_MQUEUE) || defined(CONFIG_SYSVIPC)
#define INIT_IPC_NS(ns) .ns = &init_ipc_ns, #define INIT_IPC_NS(ns) .ns = &init_ipc_ns,
#else
#define INIT_IPC_NS(ns)
#endif
#ifdef CONFIG_SYSVIPC
extern int register_ipcns_notifier(struct ipc_namespace *); extern int register_ipcns_notifier(struct ipc_namespace *);
extern int cond_register_ipcns_notifier(struct ipc_namespace *); extern int cond_register_ipcns_notifier(struct ipc_namespace *);
extern void unregister_ipcns_notifier(struct ipc_namespace *); extern void unregister_ipcns_notifier(struct ipc_namespace *);
extern int ipcns_notify(unsigned long); extern int ipcns_notify(unsigned long);
#else /* CONFIG_SYSVIPC */ #else /* CONFIG_SYSVIPC */
#define INIT_IPC_NS(ns) static inline int register_ipcns_notifier(struct ipc_namespace *ns)
{ return 0; }
static inline int cond_register_ipcns_notifier(struct ipc_namespace *ns)
{ return 0; }
static inline void unregister_ipcns_notifier(struct ipc_namespace *ns) { }
static inline int ipcns_notify(unsigned long l) { return 0; }
#endif /* CONFIG_SYSVIPC */ #endif /* CONFIG_SYSVIPC */
#if defined(CONFIG_SYSVIPC) && defined(CONFIG_IPC_NS) #ifdef CONFIG_POSIX_MQUEUE
extern void mq_init_ns(struct ipc_namespace *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 */
#else
#define mq_init_ns(ns) ((void) 0)
#endif
#if defined(CONFIG_IPC_NS)
extern void free_ipc_ns(struct kref *kref); extern void free_ipc_ns(struct kref *kref);
extern struct ipc_namespace *copy_ipcs(unsigned long flags, extern struct ipc_namespace *copy_ipcs(unsigned long flags,
struct ipc_namespace *ns); struct ipc_namespace *ns);
......
...@@ -670,10 +670,10 @@ config UTS_NS ...@@ -670,10 +670,10 @@ config UTS_NS
config IPC_NS config IPC_NS
bool "IPC namespace" bool "IPC namespace"
depends on NAMESPACES && SYSVIPC depends on NAMESPACES && (SYSVIPC || POSIX_MQUEUE)
help help
In this namespace tasks work with IPC ids which correspond to In this namespace tasks work with IPC ids which correspond to
different IPC objects in different namespaces different IPC objects in different namespaces.
config USER_NS config USER_NS
bool "User namespace (EXPERIMENTAL)" bool "User namespace (EXPERIMENTAL)"
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/nsproxy.h> #include <linux/nsproxy.h>
#include <linux/pid.h> #include <linux/pid.h>
#include <linux/ipc_namespace.h>
#include <net/sock.h> #include <net/sock.h>
#include "util.h" #include "util.h"
...@@ -46,12 +47,6 @@ ...@@ -46,12 +47,6 @@
#define STATE_PENDING 1 #define STATE_PENDING 1
#define STATE_READY 2 #define STATE_READY 2
/* 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 */
/* /*
* Define the ranges various user-specified maximum values can * Define the ranges various user-specified maximum values can
* be set to. * be set to.
...@@ -95,12 +90,6 @@ static void remove_notification(struct mqueue_inode_info *info); ...@@ -95,12 +90,6 @@ static void remove_notification(struct mqueue_inode_info *info);
static spinlock_t mq_lock; static spinlock_t mq_lock;
static struct kmem_cache *mqueue_inode_cachep; static struct kmem_cache *mqueue_inode_cachep;
static struct vfsmount *mqueue_mnt;
static unsigned int queues_count;
static unsigned int queues_max = DFLT_QUEUESMAX;
static unsigned int msg_max = DFLT_MSGMAX;
static unsigned int msgsize_max = DFLT_MSGSIZEMAX;
static struct ctl_table_header * mq_sysctl_table; static struct ctl_table_header * mq_sysctl_table;
...@@ -109,11 +98,27 @@ static inline struct mqueue_inode_info *MQUEUE_I(struct inode *inode) ...@@ -109,11 +98,27 @@ static inline struct mqueue_inode_info *MQUEUE_I(struct inode *inode)
return container_of(inode, struct mqueue_inode_info, vfs_inode); return container_of(inode, struct mqueue_inode_info, vfs_inode);
} }
void mq_init_ns(struct ipc_namespace *ns)
{
ns->mq_queues_count = 0;
ns->mq_queues_max = DFLT_QUEUESMAX;
ns->mq_msg_max = DFLT_MSGMAX;
ns->mq_msgsize_max = DFLT_MSGSIZEMAX;
ns->mq_mnt = mntget(init_ipc_ns.mq_mnt);
}
void mq_exit_ns(struct ipc_namespace *ns)
{
/* will need to clear out ns->mq_mnt->mnt_sb->s_fs_info here */
mntput(ns->mq_mnt);
}
static struct inode *mqueue_get_inode(struct super_block *sb, int mode, static struct inode *mqueue_get_inode(struct super_block *sb, int mode,
struct mq_attr *attr) struct mq_attr *attr)
{ {
struct user_struct *u = current_user(); struct user_struct *u = current_user();
struct inode *inode; struct inode *inode;
struct ipc_namespace *ipc_ns = &init_ipc_ns;
inode = new_inode(sb); inode = new_inode(sb);
if (inode) { if (inode) {
...@@ -141,8 +146,8 @@ static struct inode *mqueue_get_inode(struct super_block *sb, int mode, ...@@ -141,8 +146,8 @@ static struct inode *mqueue_get_inode(struct super_block *sb, int mode,
info->qsize = 0; info->qsize = 0;
info->user = NULL; /* set when all is ok */ info->user = NULL; /* set when all is ok */
memset(&info->attr, 0, sizeof(info->attr)); memset(&info->attr, 0, sizeof(info->attr));
info->attr.mq_maxmsg = msg_max; info->attr.mq_maxmsg = ipc_ns->mq_msg_max;
info->attr.mq_msgsize = msgsize_max; info->attr.mq_msgsize = ipc_ns->mq_msgsize_max;
if (attr) { if (attr) {
info->attr.mq_maxmsg = attr->mq_maxmsg; info->attr.mq_maxmsg = attr->mq_maxmsg;
info->attr.mq_msgsize = attr->mq_msgsize; info->attr.mq_msgsize = attr->mq_msgsize;
...@@ -242,6 +247,7 @@ static void mqueue_delete_inode(struct inode *inode) ...@@ -242,6 +247,7 @@ static void mqueue_delete_inode(struct inode *inode)
struct user_struct *user; struct user_struct *user;
unsigned long mq_bytes; unsigned long mq_bytes;
int i; int i;
struct ipc_namespace *ipc_ns = &init_ipc_ns;
if (S_ISDIR(inode->i_mode)) { if (S_ISDIR(inode->i_mode)) {
clear_inode(inode); clear_inode(inode);
...@@ -262,7 +268,7 @@ static void mqueue_delete_inode(struct inode *inode) ...@@ -262,7 +268,7 @@ static void mqueue_delete_inode(struct inode *inode)
if (user) { if (user) {
spin_lock(&mq_lock); spin_lock(&mq_lock);
user->mq_bytes -= mq_bytes; user->mq_bytes -= mq_bytes;
queues_count--; ipc_ns->mq_queues_count--;
spin_unlock(&mq_lock); spin_unlock(&mq_lock);
free_uid(user); free_uid(user);
} }
...@@ -274,21 +280,23 @@ static int mqueue_create(struct inode *dir, struct dentry *dentry, ...@@ -274,21 +280,23 @@ static int mqueue_create(struct inode *dir, struct dentry *dentry,
struct inode *inode; struct inode *inode;
struct mq_attr *attr = dentry->d_fsdata; struct mq_attr *attr = dentry->d_fsdata;
int error; int error;
struct ipc_namespace *ipc_ns = &init_ipc_ns;
spin_lock(&mq_lock); spin_lock(&mq_lock);
if (queues_count >= queues_max && !capable(CAP_SYS_RESOURCE)) { if (ipc_ns->mq_queues_count >= ipc_ns->mq_queues_max &&
!capable(CAP_SYS_RESOURCE)) {
error = -ENOSPC; error = -ENOSPC;
goto out_lock; goto out_unlock;
} }
queues_count++; ipc_ns->mq_queues_count++;
spin_unlock(&mq_lock); spin_unlock(&mq_lock);
inode = mqueue_get_inode(dir->i_sb, mode, attr); inode = mqueue_get_inode(dir->i_sb, mode, attr);
if (!inode) { if (!inode) {
error = -ENOMEM; error = -ENOMEM;
spin_lock(&mq_lock); spin_lock(&mq_lock);
queues_count--; ipc_ns->mq_queues_count--;
goto out_lock; goto out_unlock;
} }
dir->i_size += DIRENT_SIZE; dir->i_size += DIRENT_SIZE;
...@@ -297,7 +305,7 @@ static int mqueue_create(struct inode *dir, struct dentry *dentry, ...@@ -297,7 +305,7 @@ static int mqueue_create(struct inode *dir, struct dentry *dentry,
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
dget(dentry); dget(dentry);
return 0; return 0;
out_lock: out_unlock:
spin_unlock(&mq_lock); spin_unlock(&mq_lock);
return error; return error;
} }
...@@ -562,7 +570,7 @@ static void remove_notification(struct mqueue_inode_info *info) ...@@ -562,7 +570,7 @@ static void remove_notification(struct mqueue_inode_info *info)
info->notify_owner = NULL; info->notify_owner = NULL;
} }
static int mq_attr_ok(struct mq_attr *attr) static int mq_attr_ok(struct ipc_namespace *ipc_ns, struct mq_attr *attr)
{ {
if (attr->mq_maxmsg <= 0 || attr->mq_msgsize <= 0) if (attr->mq_maxmsg <= 0 || attr->mq_msgsize <= 0)
return 0; return 0;
...@@ -570,8 +578,8 @@ static int mq_attr_ok(struct mq_attr *attr) ...@@ -570,8 +578,8 @@ static int mq_attr_ok(struct mq_attr *attr)
if (attr->mq_maxmsg > HARD_MSGMAX) if (attr->mq_maxmsg > HARD_MSGMAX)
return 0; return 0;
} else { } else {
if (attr->mq_maxmsg > msg_max || if (attr->mq_maxmsg > ipc_ns->mq_msg_max ||
attr->mq_msgsize > msgsize_max) attr->mq_msgsize > ipc_ns->mq_msgsize_max)
return 0; return 0;
} }
/* check for overflow */ /* check for overflow */
...@@ -587,8 +595,9 @@ static int mq_attr_ok(struct mq_attr *attr) ...@@ -587,8 +595,9 @@ static int mq_attr_ok(struct mq_attr *attr)
/* /*
* Invoked when creating a new queue via sys_mq_open * Invoked when creating a new queue via sys_mq_open
*/ */
static struct file *do_create(struct dentry *dir, struct dentry *dentry, static struct file *do_create(struct ipc_namespace *ipc_ns, struct dentry *dir,
int oflag, mode_t mode, struct mq_attr *attr) struct dentry *dentry, int oflag, mode_t mode,
struct mq_attr *attr)
{ {
const struct cred *cred = current_cred(); const struct cred *cred = current_cred();
struct file *result; struct file *result;
...@@ -596,14 +605,14 @@ static struct file *do_create(struct dentry *dir, struct dentry *dentry, ...@@ -596,14 +605,14 @@ static struct file *do_create(struct dentry *dir, struct dentry *dentry,
if (attr) { if (attr) {
ret = -EINVAL; ret = -EINVAL;
if (!mq_attr_ok(attr)) if (!mq_attr_ok(ipc_ns, attr))
goto out; goto out;
/* store for use during create */ /* store for use during create */
dentry->d_fsdata = attr; dentry->d_fsdata = attr;
} }
mode &= ~current_umask(); mode &= ~current_umask();
ret = mnt_want_write(mqueue_mnt); ret = mnt_want_write(ipc_ns->mq_mnt);
if (ret) if (ret)
goto out; goto out;
ret = vfs_create(dir->d_inode, dentry, mode, NULL); ret = vfs_create(dir->d_inode, dentry, mode, NULL);
...@@ -611,24 +620,25 @@ static struct file *do_create(struct dentry *dir, struct dentry *dentry, ...@@ -611,24 +620,25 @@ static struct file *do_create(struct dentry *dir, struct dentry *dentry,
if (ret) if (ret)
goto out_drop_write; goto out_drop_write;
result = dentry_open(dentry, mqueue_mnt, oflag, cred); result = dentry_open(dentry, ipc_ns->mq_mnt, oflag, cred);
/* /*
* dentry_open() took a persistent mnt_want_write(), * dentry_open() took a persistent mnt_want_write(),
* so we can now drop this one. * so we can now drop this one.
*/ */
mnt_drop_write(mqueue_mnt); mnt_drop_write(ipc_ns->mq_mnt);
return result; return result;
out_drop_write: out_drop_write:
mnt_drop_write(mqueue_mnt); mnt_drop_write(ipc_ns->mq_mnt);
out: out:
dput(dentry); dput(dentry);
mntput(mqueue_mnt); mntput(ipc_ns->mq_mnt);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
/* Opens existing queue */ /* Opens existing queue */
static struct file *do_open(struct dentry *dentry, int oflag) static struct file *do_open(struct ipc_namespace *ipc_ns,
struct dentry *dentry, int oflag)
{ {
const struct cred *cred = current_cred(); const struct cred *cred = current_cred();
...@@ -637,17 +647,17 @@ static struct file *do_open(struct dentry *dentry, int oflag) ...@@ -637,17 +647,17 @@ static struct file *do_open(struct dentry *dentry, int oflag)
if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) { if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) {
dput(dentry); dput(dentry);
mntput(mqueue_mnt); mntput(ipc_ns->mq_mnt);
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
if (inode_permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE])) { if (inode_permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE])) {
dput(dentry); dput(dentry);
mntput(mqueue_mnt); mntput(ipc_ns->mq_mnt);
return ERR_PTR(-EACCES); return ERR_PTR(-EACCES);
} }
return dentry_open(dentry, mqueue_mnt, oflag, cred); return dentry_open(dentry, ipc_ns->mq_mnt, oflag, cred);
} }
SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode, SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode,
...@@ -658,6 +668,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode, ...@@ -658,6 +668,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode,
char *name; char *name;
struct mq_attr attr; struct mq_attr attr;
int fd, error; int fd, error;
struct ipc_namespace *ipc_ns = &init_ipc_ns;
if (u_attr && copy_from_user(&attr, u_attr, sizeof(struct mq_attr))) if (u_attr && copy_from_user(&attr, u_attr, sizeof(struct mq_attr)))
return -EFAULT; return -EFAULT;
...@@ -671,13 +682,13 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode, ...@@ -671,13 +682,13 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode,
if (fd < 0) if (fd < 0)
goto out_putname; goto out_putname;
mutex_lock(&mqueue_mnt->mnt_root->d_inode->i_mutex); mutex_lock(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex);
dentry = lookup_one_len(name, mqueue_mnt->mnt_root, strlen(name)); dentry = lookup_one_len(name, ipc_ns->mq_mnt->mnt_root, strlen(name));
if (IS_ERR(dentry)) { if (IS_ERR(dentry)) {
error = PTR_ERR(dentry); error = PTR_ERR(dentry);
goto out_err; goto out_err;
} }
mntget(mqueue_mnt); mntget(ipc_ns->mq_mnt);
if (oflag & O_CREAT) { if (oflag & O_CREAT) {
if (dentry->d_inode) { /* entry already exists */ if (dentry->d_inode) { /* entry already exists */
...@@ -685,10 +696,10 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode, ...@@ -685,10 +696,10 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode,
error = -EEXIST; error = -EEXIST;
if (oflag & O_EXCL) if (oflag & O_EXCL)
goto out; goto out;
filp = do_open(dentry, oflag); filp = do_open(ipc_ns, dentry, oflag);
} else { } else {
filp = do_create(mqueue_mnt->mnt_root, dentry, filp = do_create(ipc_ns, ipc_ns->mq_mnt->mnt_root,
oflag, mode, dentry, oflag, mode,
u_attr ? &attr : NULL); u_attr ? &attr : NULL);
} }
} else { } else {
...@@ -696,7 +707,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode, ...@@ -696,7 +707,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode,
if (!dentry->d_inode) if (!dentry->d_inode)
goto out; goto out;
audit_inode(name, dentry); audit_inode(name, dentry);
filp = do_open(dentry, oflag); filp = do_open(ipc_ns, dentry, oflag);
} }
if (IS_ERR(filp)) { if (IS_ERR(filp)) {
...@@ -709,13 +720,13 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode, ...@@ -709,13 +720,13 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode,
out: out:
dput(dentry); dput(dentry);
mntput(mqueue_mnt); mntput(ipc_ns->mq_mnt);
out_putfd: out_putfd:
put_unused_fd(fd); put_unused_fd(fd);
out_err: out_err:
fd = error; fd = error;
out_upsem: out_upsem:
mutex_unlock(&mqueue_mnt->mnt_root->d_inode->i_mutex); mutex_unlock(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex);
out_putname: out_putname:
putname(name); putname(name);
return fd; return fd;
...@@ -727,14 +738,15 @@ SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name) ...@@ -727,14 +738,15 @@ SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name)
char *name; char *name;
struct dentry *dentry; struct dentry *dentry;
struct inode *inode = NULL; struct inode *inode = NULL;
struct ipc_namespace *ipc_ns = &init_ipc_ns;
name = getname(u_name); name = getname(u_name);
if (IS_ERR(name)) if (IS_ERR(name))
return PTR_ERR(name); return PTR_ERR(name);
mutex_lock_nested(&mqueue_mnt->mnt_root->d_inode->i_mutex, mutex_lock_nested(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex,
I_MUTEX_PARENT); I_MUTEX_PARENT);
dentry = lookup_one_len(name, mqueue_mnt->mnt_root, strlen(name)); dentry = lookup_one_len(name, ipc_ns->mq_mnt->mnt_root, strlen(name));
if (IS_ERR(dentry)) { if (IS_ERR(dentry)) {
err = PTR_ERR(dentry); err = PTR_ERR(dentry);
goto out_unlock; goto out_unlock;
...@@ -748,16 +760,16 @@ SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name) ...@@ -748,16 +760,16 @@ SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name)
inode = dentry->d_inode; inode = dentry->d_inode;
if (inode) if (inode)
atomic_inc(&inode->i_count); atomic_inc(&inode->i_count);
err = mnt_want_write(mqueue_mnt); err = mnt_want_write(ipc_ns->mq_mnt);
if (err) if (err)
goto out_err; goto out_err;
err = vfs_unlink(dentry->d_parent->d_inode, dentry); err = vfs_unlink(dentry->d_parent->d_inode, dentry);
mnt_drop_write(mqueue_mnt); mnt_drop_write(ipc_ns->mq_mnt);
out_err: out_err:
dput(dentry); dput(dentry);
out_unlock: out_unlock:
mutex_unlock(&mqueue_mnt->mnt_root->d_inode->i_mutex); mutex_unlock(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex);
putname(name); putname(name);
if (inode) if (inode)
iput(inode); iput(inode);
...@@ -1214,14 +1226,14 @@ static int msg_maxsize_limit_max = MAX_MSGSIZEMAX; ...@@ -1214,14 +1226,14 @@ static int msg_maxsize_limit_max = MAX_MSGSIZEMAX;
static ctl_table mq_sysctls[] = { static ctl_table mq_sysctls[] = {
{ {
.procname = "queues_max", .procname = "queues_max",
.data = &queues_max, .data = &init_ipc_ns.mq_queues_max,
.maxlen = sizeof(int), .maxlen = sizeof(int),
.mode = 0644, .mode = 0644,
.proc_handler = &proc_dointvec, .proc_handler = &proc_dointvec,
}, },
{ {
.procname = "msg_max", .procname = "msg_max",
.data = &msg_max, .data = &init_ipc_ns.mq_msg_max,
.maxlen = sizeof(int), .maxlen = sizeof(int),
.mode = 0644, .mode = 0644,
.proc_handler = &proc_dointvec_minmax, .proc_handler = &proc_dointvec_minmax,
...@@ -1230,7 +1242,7 @@ static ctl_table mq_sysctls[] = { ...@@ -1230,7 +1242,7 @@ static ctl_table mq_sysctls[] = {
}, },
{ {
.procname = "msgsize_max", .procname = "msgsize_max",
.data = &msgsize_max, .data = &init_ipc_ns.mq_msgsize_max,
.maxlen = sizeof(int), .maxlen = sizeof(int),
.mode = 0644, .mode = 0644,
.proc_handler = &proc_dointvec_minmax, .proc_handler = &proc_dointvec_minmax,
...@@ -1276,13 +1288,13 @@ static int __init init_mqueue_fs(void) ...@@ -1276,13 +1288,13 @@ static int __init init_mqueue_fs(void)
if (error) if (error)
goto out_sysctl; goto out_sysctl;
if (IS_ERR(mqueue_mnt = kern_mount(&mqueue_fs_type))) { init_ipc_ns.mq_mnt = kern_mount(&mqueue_fs_type);
error = PTR_ERR(mqueue_mnt); if (IS_ERR(init_ipc_ns.mq_mnt)) {
error = PTR_ERR(init_ipc_ns.mq_mnt);
goto out_filesystem; goto out_filesystem;
} }
/* internal initialization - not common for vfs */ /* internal initialization - not common for vfs */
queues_count = 0;
spin_lock_init(&mq_lock); spin_lock_init(&mq_lock);
return 0; return 0;
......
...@@ -13,10 +13,32 @@ ...@@ -13,10 +13,32 @@
#include <linux/security.h> #include <linux/security.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/ipc.h> #include <linux/ipc.h>
#include <linux/ipc_namespace.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include "util.h" #include "util.h"
/*
* The next 2 defines are here bc this is the only file
* compiled when either CONFIG_SYSVIPC and CONFIG_POSIX_MQUEUE
* and not CONFIG_IPC_NS.
*/
struct ipc_namespace init_ipc_ns = {
.kref = {
/* It's not for this patch to change, but should this be 1? */
.refcount = ATOMIC_INIT(2),
},
#ifdef CONFIG_POSIX_MQUEUE
.mq_mnt = NULL,
.mq_queues_count = 0,
.mq_queues_max = DFLT_QUEUESMAX,
.mq_msg_max = DFLT_MSGMAX,
.mq_msgsize_max = DFLT_MSGSIZEMAX,
#endif
};
atomic_t nr_ipc_ns = ATOMIC_INIT(1);
struct msg_msgseg { struct msg_msgseg {
struct msg_msgseg* next; struct msg_msgseg* next;
/* the next part of the message follows immediately */ /* the next part of the message follows immediately */
......
...@@ -25,6 +25,7 @@ static struct ipc_namespace *clone_ipc_ns(struct ipc_namespace *old_ns) ...@@ -25,6 +25,7 @@ static struct ipc_namespace *clone_ipc_ns(struct ipc_namespace *old_ns)
sem_init_ns(ns); sem_init_ns(ns);
msg_init_ns(ns); msg_init_ns(ns);
shm_init_ns(ns); shm_init_ns(ns);
mq_init_ns(ns);
/* /*
* msgmni has already been computed for the new ipc ns. * msgmni has already been computed for the new ipc ns.
...@@ -101,6 +102,7 @@ void free_ipc_ns(struct kref *kref) ...@@ -101,6 +102,7 @@ void free_ipc_ns(struct kref *kref)
sem_exit_ns(ns); sem_exit_ns(ns);
msg_exit_ns(ns); msg_exit_ns(ns);
shm_exit_ns(ns); shm_exit_ns(ns);
mq_exit_ns(ns);
kfree(ns); kfree(ns);
atomic_dec(&nr_ipc_ns); atomic_dec(&nr_ipc_ns);
......
...@@ -47,15 +47,6 @@ struct ipc_proc_iface { ...@@ -47,15 +47,6 @@ struct ipc_proc_iface {
int (*show)(struct seq_file *, void *); int (*show)(struct seq_file *, void *);
}; };
struct ipc_namespace init_ipc_ns = {
.kref = {
.refcount = ATOMIC_INIT(2),
},
};
atomic_t nr_ipc_ns = ATOMIC_INIT(1);
#ifdef CONFIG_MEMORY_HOTPLUG #ifdef CONFIG_MEMORY_HOTPLUG
static void ipc_memory_notifier(struct work_struct *work) static void ipc_memory_notifier(struct work_struct *work)
......
...@@ -20,6 +20,13 @@ void shm_init (void); ...@@ -20,6 +20,13 @@ void shm_init (void);
struct ipc_namespace; struct ipc_namespace;
#ifdef CONFIG_POSIX_MQUEUE
void mq_exit_ns(struct ipc_namespace *ns);
#else
static inline void mq_exit_ns(struct ipc_namespace *ns) { }
#endif
#ifdef CONFIG_SYSVIPC
void sem_init_ns(struct ipc_namespace *ns); void sem_init_ns(struct ipc_namespace *ns);
void msg_init_ns(struct ipc_namespace *ns); void msg_init_ns(struct ipc_namespace *ns);
void shm_init_ns(struct ipc_namespace *ns); void shm_init_ns(struct ipc_namespace *ns);
...@@ -27,6 +34,15 @@ void shm_init_ns(struct ipc_namespace *ns); ...@@ -27,6 +34,15 @@ void shm_init_ns(struct ipc_namespace *ns);
void sem_exit_ns(struct ipc_namespace *ns); void sem_exit_ns(struct ipc_namespace *ns);
void msg_exit_ns(struct ipc_namespace *ns); void msg_exit_ns(struct ipc_namespace *ns);
void shm_exit_ns(struct ipc_namespace *ns); void shm_exit_ns(struct ipc_namespace *ns);
#else
static inline void sem_init_ns(struct ipc_namespace *ns) { }
static inline void msg_init_ns(struct ipc_namespace *ns) { }
static inline void shm_init_ns(struct ipc_namespace *ns) { }
static inline void sem_exit_ns(struct ipc_namespace *ns) { }
static inline void msg_exit_ns(struct ipc_namespace *ns) { }
static inline void shm_exit_ns(struct ipc_namespace *ns) { }
#endif
/* /*
* Structure that holds the parameters needed by the ipc operations * Structure that holds the parameters needed by the ipc operations
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment