aboutsummaryrefslogtreecommitdiffstats
path: root/ipc/mqueue.c
diff options
context:
space:
mode:
Diffstat (limited to 'ipc/mqueue.c')
-rw-r--r--ipc/mqueue.c74
1 files changed, 55 insertions, 19 deletions
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 9f05837a86a6..738579191fd2 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -325,8 +325,9 @@ err:
325static int mqueue_fill_super(struct super_block *sb, void *data, int silent) 325static int mqueue_fill_super(struct super_block *sb, void *data, int silent)
326{ 326{
327 struct inode *inode; 327 struct inode *inode;
328 struct ipc_namespace *ns = sb->s_fs_info; 328 struct ipc_namespace *ns = data;
329 329
330 sb->s_fs_info = ns;
330 sb->s_iflags |= SB_I_NOEXEC | SB_I_NODEV; 331 sb->s_iflags |= SB_I_NOEXEC | SB_I_NODEV;
331 sb->s_blocksize = PAGE_SIZE; 332 sb->s_blocksize = PAGE_SIZE;
332 sb->s_blocksize_bits = PAGE_SHIFT; 333 sb->s_blocksize_bits = PAGE_SHIFT;
@@ -343,18 +344,44 @@ static int mqueue_fill_super(struct super_block *sb, void *data, int silent)
343 return 0; 344 return 0;
344} 345}
345 346
347static struct file_system_type mqueue_fs_type;
348/*
349 * Return value is pinned only by reference in ->mq_mnt; it will
350 * live until ipcns dies. Caller does not need to drop it.
351 */
352static struct vfsmount *mq_internal_mount(void)
353{
354 struct ipc_namespace *ns = current->nsproxy->ipc_ns;
355 struct vfsmount *m = ns->mq_mnt;
356 if (m)
357 return m;
358 m = kern_mount_data(&mqueue_fs_type, ns);
359 spin_lock(&mq_lock);
360 if (unlikely(ns->mq_mnt)) {
361 spin_unlock(&mq_lock);
362 if (!IS_ERR(m))
363 kern_unmount(m);
364 return ns->mq_mnt;
365 }
366 if (!IS_ERR(m))
367 ns->mq_mnt = m;
368 spin_unlock(&mq_lock);
369 return m;
370}
371
346static struct dentry *mqueue_mount(struct file_system_type *fs_type, 372static struct dentry *mqueue_mount(struct file_system_type *fs_type,
347 int flags, const char *dev_name, 373 int flags, const char *dev_name,
348 void *data) 374 void *data)
349{ 375{
350 struct ipc_namespace *ns; 376 struct vfsmount *m;
351 if (flags & SB_KERNMOUNT) { 377 if (flags & SB_KERNMOUNT)
352 ns = data; 378 return mount_nodev(fs_type, flags, data, mqueue_fill_super);
353 data = NULL; 379 m = mq_internal_mount();
354 } else { 380 if (IS_ERR(m))
355 ns = current->nsproxy->ipc_ns; 381 return ERR_CAST(m);
356 } 382 atomic_inc(&m->mnt_sb->s_active);
357 return mount_ns(fs_type, flags, data, ns, ns->user_ns, mqueue_fill_super); 383 down_write(&m->mnt_sb->s_umount);
384 return dget(m->mnt_root);
358} 385}
359 386
360static void init_once(void *foo) 387static void init_once(void *foo)
@@ -743,13 +770,16 @@ static int prepare_open(struct dentry *dentry, int oflag, int ro,
743static int do_mq_open(const char __user *u_name, int oflag, umode_t mode, 770static int do_mq_open(const char __user *u_name, int oflag, umode_t mode,
744 struct mq_attr *attr) 771 struct mq_attr *attr)
745{ 772{
746 struct vfsmount *mnt = current->nsproxy->ipc_ns->mq_mnt; 773 struct vfsmount *mnt = mq_internal_mount();
747 struct dentry *root = mnt->mnt_root; 774 struct dentry *root;
748 struct filename *name; 775 struct filename *name;
749 struct path path; 776 struct path path;
750 int fd, error; 777 int fd, error;
751 int ro; 778 int ro;
752 779
780 if (IS_ERR(mnt))
781 return PTR_ERR(mnt);
782
753 audit_mq_open(oflag, mode, attr); 783 audit_mq_open(oflag, mode, attr);
754 784
755 if (IS_ERR(name = getname(u_name))) 785 if (IS_ERR(name = getname(u_name)))
@@ -760,6 +790,7 @@ static int do_mq_open(const char __user *u_name, int oflag, umode_t mode,
760 goto out_putname; 790 goto out_putname;
761 791
762 ro = mnt_want_write(mnt); /* we'll drop it in any case */ 792 ro = mnt_want_write(mnt); /* we'll drop it in any case */
793 root = mnt->mnt_root;
763 inode_lock(d_inode(root)); 794 inode_lock(d_inode(root));
764 path.dentry = lookup_one_len(name->name, root, strlen(name->name)); 795 path.dentry = lookup_one_len(name->name, root, strlen(name->name));
765 if (IS_ERR(path.dentry)) { 796 if (IS_ERR(path.dentry)) {
@@ -808,6 +839,9 @@ SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name)
808 struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns; 839 struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
809 struct vfsmount *mnt = ipc_ns->mq_mnt; 840 struct vfsmount *mnt = ipc_ns->mq_mnt;
810 841
842 if (!mnt)
843 return -ENOENT;
844
811 name = getname(u_name); 845 name = getname(u_name);
812 if (IS_ERR(name)) 846 if (IS_ERR(name))
813 return PTR_ERR(name); 847 return PTR_ERR(name);
@@ -1534,28 +1568,26 @@ int mq_init_ns(struct ipc_namespace *ns)
1534 ns->mq_msgsize_max = DFLT_MSGSIZEMAX; 1568 ns->mq_msgsize_max = DFLT_MSGSIZEMAX;
1535 ns->mq_msg_default = DFLT_MSG; 1569 ns->mq_msg_default = DFLT_MSG;
1536 ns->mq_msgsize_default = DFLT_MSGSIZE; 1570 ns->mq_msgsize_default = DFLT_MSGSIZE;
1571 ns->mq_mnt = NULL;
1537 1572
1538 ns->mq_mnt = kern_mount_data(&mqueue_fs_type, ns);
1539 if (IS_ERR(ns->mq_mnt)) {
1540 int err = PTR_ERR(ns->mq_mnt);
1541 ns->mq_mnt = NULL;
1542 return err;
1543 }
1544 return 0; 1573 return 0;
1545} 1574}
1546 1575
1547void mq_clear_sbinfo(struct ipc_namespace *ns) 1576void mq_clear_sbinfo(struct ipc_namespace *ns)
1548{ 1577{
1549 ns->mq_mnt->mnt_sb->s_fs_info = NULL; 1578 if (ns->mq_mnt)
1579 ns->mq_mnt->mnt_sb->s_fs_info = NULL;
1550} 1580}
1551 1581
1552void mq_put_mnt(struct ipc_namespace *ns) 1582void mq_put_mnt(struct ipc_namespace *ns)
1553{ 1583{
1554 kern_unmount(ns->mq_mnt); 1584 if (ns->mq_mnt)
1585 kern_unmount(ns->mq_mnt);
1555} 1586}
1556 1587
1557static int __init init_mqueue_fs(void) 1588static int __init init_mqueue_fs(void)
1558{ 1589{
1590 struct vfsmount *m;
1559 int error; 1591 int error;
1560 1592
1561 mqueue_inode_cachep = kmem_cache_create("mqueue_inode_cache", 1593 mqueue_inode_cachep = kmem_cache_create("mqueue_inode_cache",
@@ -1577,6 +1609,10 @@ static int __init init_mqueue_fs(void)
1577 if (error) 1609 if (error)
1578 goto out_filesystem; 1610 goto out_filesystem;
1579 1611
1612 m = kern_mount_data(&mqueue_fs_type, &init_ipc_ns);
1613 if (IS_ERR(m))
1614 goto out_filesystem;
1615 init_ipc_ns.mq_mnt = m;
1580 return 0; 1616 return 0;
1581 1617
1582out_filesystem: 1618out_filesystem: