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