diff options
| -rw-r--r-- | ipc/mqueue.c | 59 |
1 files changed, 33 insertions, 26 deletions
diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 4e776f9c80e7..59302fc3643b 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c | |||
| @@ -599,15 +599,16 @@ static int mq_attr_ok(struct mq_attr *attr) | |||
| 599 | static struct file *do_create(struct dentry *dir, struct dentry *dentry, | 599 | static struct file *do_create(struct dentry *dir, struct dentry *dentry, |
| 600 | int oflag, mode_t mode, struct mq_attr __user *u_attr) | 600 | int oflag, mode_t mode, struct mq_attr __user *u_attr) |
| 601 | { | 601 | { |
| 602 | struct file *filp; | ||
| 603 | struct mq_attr attr; | 602 | struct mq_attr attr; |
| 604 | int ret; | 603 | int ret; |
| 605 | 604 | ||
| 606 | if (u_attr != NULL) { | 605 | if (u_attr) { |
| 606 | ret = -EFAULT; | ||
| 607 | if (copy_from_user(&attr, u_attr, sizeof(attr))) | 607 | if (copy_from_user(&attr, u_attr, sizeof(attr))) |
| 608 | return ERR_PTR(-EFAULT); | 608 | goto out; |
| 609 | ret = -EINVAL; | ||
| 609 | if (!mq_attr_ok(&attr)) | 610 | if (!mq_attr_ok(&attr)) |
| 610 | return ERR_PTR(-EINVAL); | 611 | goto out; |
| 611 | /* store for use during create */ | 612 | /* store for use during create */ |
| 612 | dentry->d_fsdata = &attr; | 613 | dentry->d_fsdata = &attr; |
| 613 | } | 614 | } |
| @@ -616,13 +617,14 @@ static struct file *do_create(struct dentry *dir, struct dentry *dentry, | |||
| 616 | ret = vfs_create(dir->d_inode, dentry, mode, NULL); | 617 | ret = vfs_create(dir->d_inode, dentry, mode, NULL); |
| 617 | dentry->d_fsdata = NULL; | 618 | dentry->d_fsdata = NULL; |
| 618 | if (ret) | 619 | if (ret) |
| 619 | return ERR_PTR(ret); | 620 | goto out; |
| 620 | 621 | ||
| 621 | filp = dentry_open(dentry, mqueue_mnt, oflag); | 622 | return dentry_open(dentry, mqueue_mnt, oflag); |
| 622 | if (!IS_ERR(filp)) | ||
| 623 | dget(dentry); | ||
| 624 | 623 | ||
| 625 | return filp; | 624 | out: |
| 625 | dput(dentry); | ||
| 626 | mntput(mqueue_mnt); | ||
| 627 | return ERR_PTR(ret); | ||
| 626 | } | 628 | } |
| 627 | 629 | ||
| 628 | /* Opens existing queue */ | 630 | /* Opens existing queue */ |
| @@ -630,20 +632,20 @@ static struct file *do_open(struct dentry *dentry, int oflag) | |||
| 630 | { | 632 | { |
| 631 | static int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE, | 633 | static int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE, |
| 632 | MAY_READ | MAY_WRITE }; | 634 | MAY_READ | MAY_WRITE }; |
| 633 | struct file *filp; | ||
| 634 | 635 | ||
| 635 | if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) | 636 | if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) { |
| 637 | dput(dentry); | ||
| 638 | mntput(mqueue_mnt); | ||
| 636 | return ERR_PTR(-EINVAL); | 639 | return ERR_PTR(-EINVAL); |
| 640 | } | ||
| 637 | 641 | ||
| 638 | if (permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE], NULL)) | 642 | if (permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE], NULL)) { |
| 643 | dput(dentry); | ||
| 644 | mntput(mqueue_mnt); | ||
| 639 | return ERR_PTR(-EACCES); | 645 | return ERR_PTR(-EACCES); |
| 646 | } | ||
| 640 | 647 | ||
| 641 | filp = dentry_open(dentry, mqueue_mnt, oflag); | 648 | return dentry_open(dentry, mqueue_mnt, oflag); |
| 642 | |||
| 643 | if (!IS_ERR(filp)) | ||
| 644 | dget(dentry); | ||
| 645 | |||
| 646 | return filp; | ||
| 647 | } | 649 | } |
| 648 | 650 | ||
| 649 | asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, | 651 | asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, |
| @@ -671,17 +673,20 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, | |||
| 671 | 673 | ||
| 672 | if (oflag & O_CREAT) { | 674 | if (oflag & O_CREAT) { |
| 673 | if (dentry->d_inode) { /* entry already exists */ | 675 | if (dentry->d_inode) { /* entry already exists */ |
| 674 | filp = (oflag & O_EXCL) ? ERR_PTR(-EEXIST) : | 676 | error = -EEXIST; |
| 675 | do_open(dentry, oflag); | 677 | if (oflag & O_EXCL) |
| 678 | goto out; | ||
| 679 | filp = do_open(dentry, oflag); | ||
| 676 | } else { | 680 | } else { |
| 677 | filp = do_create(mqueue_mnt->mnt_root, dentry, | 681 | filp = do_create(mqueue_mnt->mnt_root, dentry, |
| 678 | oflag, mode, u_attr); | 682 | oflag, mode, u_attr); |
| 679 | } | 683 | } |
| 680 | } else | 684 | } else { |
| 681 | filp = (dentry->d_inode) ? do_open(dentry, oflag) : | 685 | error = -ENOENT; |
| 682 | ERR_PTR(-ENOENT); | 686 | if (!dentry->d_inode) |
| 683 | 687 | goto out; | |
| 684 | dput(dentry); | 688 | filp = do_open(dentry, oflag); |
| 689 | } | ||
| 685 | 690 | ||
| 686 | if (IS_ERR(filp)) { | 691 | if (IS_ERR(filp)) { |
| 687 | error = PTR_ERR(filp); | 692 | error = PTR_ERR(filp); |
| @@ -692,8 +697,10 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, | |||
| 692 | fd_install(fd, filp); | 697 | fd_install(fd, filp); |
| 693 | goto out_upsem; | 698 | goto out_upsem; |
| 694 | 699 | ||
| 695 | out_putfd: | 700 | out: |
| 701 | dput(dentry); | ||
| 696 | mntput(mqueue_mnt); | 702 | mntput(mqueue_mnt); |
| 703 | out_putfd: | ||
| 697 | put_unused_fd(fd); | 704 | put_unused_fd(fd); |
| 698 | out_err: | 705 | out_err: |
| 699 | fd = error; | 706 | fd = error; |
