aboutsummaryrefslogtreecommitdiffstats
path: root/ipc/mqueue.c
diff options
context:
space:
mode:
Diffstat (limited to 'ipc/mqueue.c')
-rw-r--r--ipc/mqueue.c98
1 files changed, 49 insertions, 49 deletions
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index d9393f8e4c3e..eddb6247a553 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -120,7 +120,6 @@ static struct inode *mqueue_get_inode(struct super_block *sb, int mode,
120 inode->i_mode = mode; 120 inode->i_mode = mode;
121 inode->i_uid = current_fsuid(); 121 inode->i_uid = current_fsuid();
122 inode->i_gid = current_fsgid(); 122 inode->i_gid = current_fsgid();
123 inode->i_blocks = 0;
124 inode->i_mtime = inode->i_ctime = inode->i_atime = 123 inode->i_mtime = inode->i_ctime = inode->i_atime =
125 CURRENT_TIME; 124 CURRENT_TIME;
126 125
@@ -524,31 +523,27 @@ static void __do_notify(struct mqueue_inode_info *info)
524 wake_up(&info->wait_q); 523 wake_up(&info->wait_q);
525} 524}
526 525
527static long prepare_timeout(const struct timespec __user *u_arg) 526static long prepare_timeout(struct timespec *p)
528{ 527{
529 struct timespec ts, nowts; 528 struct timespec nowts;
530 long timeout; 529 long timeout;
531 530
532 if (u_arg) { 531 if (p) {
533 if (unlikely(copy_from_user(&ts, u_arg, 532 if (unlikely(p->tv_nsec < 0 || p->tv_sec < 0
534 sizeof(struct timespec)))) 533 || p->tv_nsec >= NSEC_PER_SEC))
535 return -EFAULT;
536
537 if (unlikely(ts.tv_nsec < 0 || ts.tv_sec < 0
538 || ts.tv_nsec >= NSEC_PER_SEC))
539 return -EINVAL; 534 return -EINVAL;
540 nowts = CURRENT_TIME; 535 nowts = CURRENT_TIME;
541 /* first subtract as jiffies can't be too big */ 536 /* first subtract as jiffies can't be too big */
542 ts.tv_sec -= nowts.tv_sec; 537 p->tv_sec -= nowts.tv_sec;
543 if (ts.tv_nsec < nowts.tv_nsec) { 538 if (p->tv_nsec < nowts.tv_nsec) {
544 ts.tv_nsec += NSEC_PER_SEC; 539 p->tv_nsec += NSEC_PER_SEC;
545 ts.tv_sec--; 540 p->tv_sec--;
546 } 541 }
547 ts.tv_nsec -= nowts.tv_nsec; 542 p->tv_nsec -= nowts.tv_nsec;
548 if (ts.tv_sec < 0) 543 if (p->tv_sec < 0)
549 return 0; 544 return 0;
550 545
551 timeout = timespec_to_jiffies(&ts) + 1; 546 timeout = timespec_to_jiffies(p) + 1;
552 } else 547 } else
553 return MAX_SCHEDULE_TIMEOUT; 548 return MAX_SCHEDULE_TIMEOUT;
554 549
@@ -592,22 +587,18 @@ static int mq_attr_ok(struct mq_attr *attr)
592 * Invoked when creating a new queue via sys_mq_open 587 * Invoked when creating a new queue via sys_mq_open
593 */ 588 */
594static struct file *do_create(struct dentry *dir, struct dentry *dentry, 589static struct file *do_create(struct dentry *dir, struct dentry *dentry,
595 int oflag, mode_t mode, struct mq_attr __user *u_attr) 590 int oflag, mode_t mode, struct mq_attr *attr)
596{ 591{
597 const struct cred *cred = current_cred(); 592 const struct cred *cred = current_cred();
598 struct mq_attr attr;
599 struct file *result; 593 struct file *result;
600 int ret; 594 int ret;
601 595
602 if (u_attr) { 596 if (attr) {
603 ret = -EFAULT;
604 if (copy_from_user(&attr, u_attr, sizeof(attr)))
605 goto out;
606 ret = -EINVAL; 597 ret = -EINVAL;
607 if (!mq_attr_ok(&attr)) 598 if (!mq_attr_ok(attr))
608 goto out; 599 goto out;
609 /* store for use during create */ 600 /* store for use during create */
610 dentry->d_fsdata = &attr; 601 dentry->d_fsdata = attr;
611 } 602 }
612 603
613 mode &= ~current->fs->umask; 604 mode &= ~current->fs->umask;
@@ -664,11 +655,13 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
664 struct dentry *dentry; 655 struct dentry *dentry;
665 struct file *filp; 656 struct file *filp;
666 char *name; 657 char *name;
658 struct mq_attr attr;
667 int fd, error; 659 int fd, error;
668 660
669 error = audit_mq_open(oflag, mode, u_attr); 661 if (u_attr && copy_from_user(&attr, u_attr, sizeof(struct mq_attr)))
670 if (error != 0) 662 return -EFAULT;
671 return error; 663
664 audit_mq_open(oflag, mode, u_attr ? &attr : NULL);
672 665
673 if (IS_ERR(name = getname(u_name))) 666 if (IS_ERR(name = getname(u_name)))
674 return PTR_ERR(name); 667 return PTR_ERR(name);
@@ -694,7 +687,8 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
694 filp = do_open(dentry, oflag); 687 filp = do_open(dentry, oflag);
695 } else { 688 } else {
696 filp = do_create(mqueue_mnt->mnt_root, dentry, 689 filp = do_create(mqueue_mnt->mnt_root, dentry,
697 oflag, mode, u_attr); 690 oflag, mode,
691 u_attr ? &attr : NULL);
698 } 692 }
699 } else { 693 } else {
700 error = -ENOENT; 694 error = -ENOENT;
@@ -829,17 +823,22 @@ asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr,
829 struct ext_wait_queue *receiver; 823 struct ext_wait_queue *receiver;
830 struct msg_msg *msg_ptr; 824 struct msg_msg *msg_ptr;
831 struct mqueue_inode_info *info; 825 struct mqueue_inode_info *info;
826 struct timespec ts, *p = NULL;
832 long timeout; 827 long timeout;
833 int ret; 828 int ret;
834 829
835 ret = audit_mq_timedsend(mqdes, msg_len, msg_prio, u_abs_timeout); 830 if (u_abs_timeout) {
836 if (ret != 0) 831 if (copy_from_user(&ts, u_abs_timeout,
837 return ret; 832 sizeof(struct timespec)))
833 return -EFAULT;
834 p = &ts;
835 }
838 836
839 if (unlikely(msg_prio >= (unsigned long) MQ_PRIO_MAX)) 837 if (unlikely(msg_prio >= (unsigned long) MQ_PRIO_MAX))
840 return -EINVAL; 838 return -EINVAL;
841 839
842 timeout = prepare_timeout(u_abs_timeout); 840 audit_mq_sendrecv(mqdes, msg_len, msg_prio, p);
841 timeout = prepare_timeout(p);
843 842
844 ret = -EBADF; 843 ret = -EBADF;
845 filp = fget(mqdes); 844 filp = fget(mqdes);
@@ -918,12 +917,17 @@ asmlinkage ssize_t sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr,
918 struct inode *inode; 917 struct inode *inode;
919 struct mqueue_inode_info *info; 918 struct mqueue_inode_info *info;
920 struct ext_wait_queue wait; 919 struct ext_wait_queue wait;
920 struct timespec ts, *p = NULL;
921 921
922 ret = audit_mq_timedreceive(mqdes, msg_len, u_msg_prio, u_abs_timeout); 922 if (u_abs_timeout) {
923 if (ret != 0) 923 if (copy_from_user(&ts, u_abs_timeout,
924 return ret; 924 sizeof(struct timespec)))
925 return -EFAULT;
926 p = &ts;
927 }
925 928
926 timeout = prepare_timeout(u_abs_timeout); 929 audit_mq_sendrecv(mqdes, msg_len, 0, p);
930 timeout = prepare_timeout(p);
927 931
928 ret = -EBADF; 932 ret = -EBADF;
929 filp = fget(mqdes); 933 filp = fget(mqdes);
@@ -1003,17 +1007,17 @@ asmlinkage long sys_mq_notify(mqd_t mqdes,
1003 struct mqueue_inode_info *info; 1007 struct mqueue_inode_info *info;
1004 struct sk_buff *nc; 1008 struct sk_buff *nc;
1005 1009
1006 ret = audit_mq_notify(mqdes, u_notification); 1010 if (u_notification) {
1007 if (ret != 0)
1008 return ret;
1009
1010 nc = NULL;
1011 sock = NULL;
1012 if (u_notification != NULL) {
1013 if (copy_from_user(&notification, u_notification, 1011 if (copy_from_user(&notification, u_notification,
1014 sizeof(struct sigevent))) 1012 sizeof(struct sigevent)))
1015 return -EFAULT; 1013 return -EFAULT;
1014 }
1016 1015
1016 audit_mq_notify(mqdes, u_notification ? &notification : NULL);
1017
1018 nc = NULL;
1019 sock = NULL;
1020 if (u_notification != NULL) {
1017 if (unlikely(notification.sigev_notify != SIGEV_NONE && 1021 if (unlikely(notification.sigev_notify != SIGEV_NONE &&
1018 notification.sigev_notify != SIGEV_SIGNAL && 1022 notification.sigev_notify != SIGEV_SIGNAL &&
1019 notification.sigev_notify != SIGEV_THREAD)) 1023 notification.sigev_notify != SIGEV_THREAD))
@@ -1150,11 +1154,7 @@ asmlinkage long sys_mq_getsetattr(mqd_t mqdes,
1150 omqstat = info->attr; 1154 omqstat = info->attr;
1151 omqstat.mq_flags = filp->f_flags & O_NONBLOCK; 1155 omqstat.mq_flags = filp->f_flags & O_NONBLOCK;
1152 if (u_mqstat) { 1156 if (u_mqstat) {
1153 ret = audit_mq_getsetattr(mqdes, &mqstat); 1157 audit_mq_getsetattr(mqdes, &mqstat);
1154 if (ret != 0) {
1155 spin_unlock(&info->lock);
1156 goto out_fput;
1157 }
1158 if (mqstat.mq_flags & O_NONBLOCK) 1158 if (mqstat.mq_flags & O_NONBLOCK)
1159 filp->f_flags |= O_NONBLOCK; 1159 filp->f_flags |= O_NONBLOCK;
1160 else 1160 else