aboutsummaryrefslogtreecommitdiffstats
path: root/ipc/mqueue.c
diff options
context:
space:
mode:
Diffstat (limited to 'ipc/mqueue.c')
-rw-r--r--ipc/mqueue.c129
1 files changed, 65 insertions, 64 deletions
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index d9393f8e4c3e..54b4077fed79 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
@@ -506,7 +505,8 @@ static void __do_notify(struct mqueue_inode_info *info)
506 sig_i.si_errno = 0; 505 sig_i.si_errno = 0;
507 sig_i.si_code = SI_MESGQ; 506 sig_i.si_code = SI_MESGQ;
508 sig_i.si_value = info->notify.sigev_value; 507 sig_i.si_value = info->notify.sigev_value;
509 sig_i.si_pid = task_tgid_vnr(current); 508 sig_i.si_pid = task_tgid_nr_ns(current,
509 ns_of_pid(info->notify_owner));
510 sig_i.si_uid = current_uid(); 510 sig_i.si_uid = current_uid();
511 511
512 kill_pid_info(info->notify.sigev_signo, 512 kill_pid_info(info->notify.sigev_signo,
@@ -524,31 +524,27 @@ static void __do_notify(struct mqueue_inode_info *info)
524 wake_up(&info->wait_q); 524 wake_up(&info->wait_q);
525} 525}
526 526
527static long prepare_timeout(const struct timespec __user *u_arg) 527static long prepare_timeout(struct timespec *p)
528{ 528{
529 struct timespec ts, nowts; 529 struct timespec nowts;
530 long timeout; 530 long timeout;
531 531
532 if (u_arg) { 532 if (p) {
533 if (unlikely(copy_from_user(&ts, u_arg, 533 if (unlikely(p->tv_nsec < 0 || p->tv_sec < 0
534 sizeof(struct timespec)))) 534 || 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; 535 return -EINVAL;
540 nowts = CURRENT_TIME; 536 nowts = CURRENT_TIME;
541 /* first subtract as jiffies can't be too big */ 537 /* first subtract as jiffies can't be too big */
542 ts.tv_sec -= nowts.tv_sec; 538 p->tv_sec -= nowts.tv_sec;
543 if (ts.tv_nsec < nowts.tv_nsec) { 539 if (p->tv_nsec < nowts.tv_nsec) {
544 ts.tv_nsec += NSEC_PER_SEC; 540 p->tv_nsec += NSEC_PER_SEC;
545 ts.tv_sec--; 541 p->tv_sec--;
546 } 542 }
547 ts.tv_nsec -= nowts.tv_nsec; 543 p->tv_nsec -= nowts.tv_nsec;
548 if (ts.tv_sec < 0) 544 if (p->tv_sec < 0)
549 return 0; 545 return 0;
550 546
551 timeout = timespec_to_jiffies(&ts) + 1; 547 timeout = timespec_to_jiffies(p) + 1;
552 } else 548 } else
553 return MAX_SCHEDULE_TIMEOUT; 549 return MAX_SCHEDULE_TIMEOUT;
554 550
@@ -592,22 +588,18 @@ static int mq_attr_ok(struct mq_attr *attr)
592 * Invoked when creating a new queue via sys_mq_open 588 * Invoked when creating a new queue via sys_mq_open
593 */ 589 */
594static struct file *do_create(struct dentry *dir, struct dentry *dentry, 590static struct file *do_create(struct dentry *dir, struct dentry *dentry,
595 int oflag, mode_t mode, struct mq_attr __user *u_attr) 591 int oflag, mode_t mode, struct mq_attr *attr)
596{ 592{
597 const struct cred *cred = current_cred(); 593 const struct cred *cred = current_cred();
598 struct mq_attr attr;
599 struct file *result; 594 struct file *result;
600 int ret; 595 int ret;
601 596
602 if (u_attr) { 597 if (attr) {
603 ret = -EFAULT;
604 if (copy_from_user(&attr, u_attr, sizeof(attr)))
605 goto out;
606 ret = -EINVAL; 598 ret = -EINVAL;
607 if (!mq_attr_ok(&attr)) 599 if (!mq_attr_ok(attr))
608 goto out; 600 goto out;
609 /* store for use during create */ 601 /* store for use during create */
610 dentry->d_fsdata = &attr; 602 dentry->d_fsdata = attr;
611 } 603 }
612 604
613 mode &= ~current->fs->umask; 605 mode &= ~current->fs->umask;
@@ -658,17 +650,19 @@ static struct file *do_open(struct dentry *dentry, int oflag)
658 return dentry_open(dentry, mqueue_mnt, oflag, cred); 650 return dentry_open(dentry, mqueue_mnt, oflag, cred);
659} 651}
660 652
661asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, 653SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode,
662 struct mq_attr __user *u_attr) 654 struct mq_attr __user *, u_attr)
663{ 655{
664 struct dentry *dentry; 656 struct dentry *dentry;
665 struct file *filp; 657 struct file *filp;
666 char *name; 658 char *name;
659 struct mq_attr attr;
667 int fd, error; 660 int fd, error;
668 661
669 error = audit_mq_open(oflag, mode, u_attr); 662 if (u_attr && copy_from_user(&attr, u_attr, sizeof(struct mq_attr)))
670 if (error != 0) 663 return -EFAULT;
671 return error; 664
665 audit_mq_open(oflag, mode, u_attr ? &attr : NULL);
672 666
673 if (IS_ERR(name = getname(u_name))) 667 if (IS_ERR(name = getname(u_name)))
674 return PTR_ERR(name); 668 return PTR_ERR(name);
@@ -694,7 +688,8 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
694 filp = do_open(dentry, oflag); 688 filp = do_open(dentry, oflag);
695 } else { 689 } else {
696 filp = do_create(mqueue_mnt->mnt_root, dentry, 690 filp = do_create(mqueue_mnt->mnt_root, dentry,
697 oflag, mode, u_attr); 691 oflag, mode,
692 u_attr ? &attr : NULL);
698 } 693 }
699 } else { 694 } else {
700 error = -ENOENT; 695 error = -ENOENT;
@@ -726,7 +721,7 @@ out_putname:
726 return fd; 721 return fd;
727} 722}
728 723
729asmlinkage long sys_mq_unlink(const char __user *u_name) 724SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name)
730{ 725{
731 int err; 726 int err;
732 char *name; 727 char *name;
@@ -819,9 +814,9 @@ static inline void pipelined_receive(struct mqueue_inode_info *info)
819 sender->state = STATE_READY; 814 sender->state = STATE_READY;
820} 815}
821 816
822asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr, 817SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr,
823 size_t msg_len, unsigned int msg_prio, 818 size_t, msg_len, unsigned int, msg_prio,
824 const struct timespec __user *u_abs_timeout) 819 const struct timespec __user *, u_abs_timeout)
825{ 820{
826 struct file *filp; 821 struct file *filp;
827 struct inode *inode; 822 struct inode *inode;
@@ -829,17 +824,22 @@ asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr,
829 struct ext_wait_queue *receiver; 824 struct ext_wait_queue *receiver;
830 struct msg_msg *msg_ptr; 825 struct msg_msg *msg_ptr;
831 struct mqueue_inode_info *info; 826 struct mqueue_inode_info *info;
827 struct timespec ts, *p = NULL;
832 long timeout; 828 long timeout;
833 int ret; 829 int ret;
834 830
835 ret = audit_mq_timedsend(mqdes, msg_len, msg_prio, u_abs_timeout); 831 if (u_abs_timeout) {
836 if (ret != 0) 832 if (copy_from_user(&ts, u_abs_timeout,
837 return ret; 833 sizeof(struct timespec)))
834 return -EFAULT;
835 p = &ts;
836 }
838 837
839 if (unlikely(msg_prio >= (unsigned long) MQ_PRIO_MAX)) 838 if (unlikely(msg_prio >= (unsigned long) MQ_PRIO_MAX))
840 return -EINVAL; 839 return -EINVAL;
841 840
842 timeout = prepare_timeout(u_abs_timeout); 841 audit_mq_sendrecv(mqdes, msg_len, msg_prio, p);
842 timeout = prepare_timeout(p);
843 843
844 ret = -EBADF; 844 ret = -EBADF;
845 filp = fget(mqdes); 845 filp = fget(mqdes);
@@ -907,9 +907,9 @@ out:
907 return ret; 907 return ret;
908} 908}
909 909
910asmlinkage ssize_t sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr, 910SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr,
911 size_t msg_len, unsigned int __user *u_msg_prio, 911 size_t, msg_len, unsigned int __user *, u_msg_prio,
912 const struct timespec __user *u_abs_timeout) 912 const struct timespec __user *, u_abs_timeout)
913{ 913{
914 long timeout; 914 long timeout;
915 ssize_t ret; 915 ssize_t ret;
@@ -918,12 +918,17 @@ asmlinkage ssize_t sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr,
918 struct inode *inode; 918 struct inode *inode;
919 struct mqueue_inode_info *info; 919 struct mqueue_inode_info *info;
920 struct ext_wait_queue wait; 920 struct ext_wait_queue wait;
921 struct timespec ts, *p = NULL;
921 922
922 ret = audit_mq_timedreceive(mqdes, msg_len, u_msg_prio, u_abs_timeout); 923 if (u_abs_timeout) {
923 if (ret != 0) 924 if (copy_from_user(&ts, u_abs_timeout,
924 return ret; 925 sizeof(struct timespec)))
926 return -EFAULT;
927 p = &ts;
928 }
925 929
926 timeout = prepare_timeout(u_abs_timeout); 930 audit_mq_sendrecv(mqdes, msg_len, 0, p);
931 timeout = prepare_timeout(p);
927 932
928 ret = -EBADF; 933 ret = -EBADF;
929 filp = fget(mqdes); 934 filp = fget(mqdes);
@@ -992,8 +997,8 @@ out:
992 * and he isn't currently owner of notification, will be silently discarded. 997 * and he isn't currently owner of notification, will be silently discarded.
993 * It isn't explicitly defined in the POSIX. 998 * It isn't explicitly defined in the POSIX.
994 */ 999 */
995asmlinkage long sys_mq_notify(mqd_t mqdes, 1000SYSCALL_DEFINE2(mq_notify, mqd_t, mqdes,
996 const struct sigevent __user *u_notification) 1001 const struct sigevent __user *, u_notification)
997{ 1002{
998 int ret; 1003 int ret;
999 struct file *filp; 1004 struct file *filp;
@@ -1003,17 +1008,17 @@ asmlinkage long sys_mq_notify(mqd_t mqdes,
1003 struct mqueue_inode_info *info; 1008 struct mqueue_inode_info *info;
1004 struct sk_buff *nc; 1009 struct sk_buff *nc;
1005 1010
1006 ret = audit_mq_notify(mqdes, u_notification); 1011 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, 1012 if (copy_from_user(&notification, u_notification,
1014 sizeof(struct sigevent))) 1013 sizeof(struct sigevent)))
1015 return -EFAULT; 1014 return -EFAULT;
1015 }
1016 1016
1017 audit_mq_notify(mqdes, u_notification ? &notification : NULL);
1018
1019 nc = NULL;
1020 sock = NULL;
1021 if (u_notification != NULL) {
1017 if (unlikely(notification.sigev_notify != SIGEV_NONE && 1022 if (unlikely(notification.sigev_notify != SIGEV_NONE &&
1018 notification.sigev_notify != SIGEV_SIGNAL && 1023 notification.sigev_notify != SIGEV_SIGNAL &&
1019 notification.sigev_notify != SIGEV_THREAD)) 1024 notification.sigev_notify != SIGEV_THREAD))
@@ -1118,9 +1123,9 @@ out:
1118 return ret; 1123 return ret;
1119} 1124}
1120 1125
1121asmlinkage long sys_mq_getsetattr(mqd_t mqdes, 1126SYSCALL_DEFINE3(mq_getsetattr, mqd_t, mqdes,
1122 const struct mq_attr __user *u_mqstat, 1127 const struct mq_attr __user *, u_mqstat,
1123 struct mq_attr __user *u_omqstat) 1128 struct mq_attr __user *, u_omqstat)
1124{ 1129{
1125 int ret; 1130 int ret;
1126 struct mq_attr mqstat, omqstat; 1131 struct mq_attr mqstat, omqstat;
@@ -1150,11 +1155,7 @@ asmlinkage long sys_mq_getsetattr(mqd_t mqdes,
1150 omqstat = info->attr; 1155 omqstat = info->attr;
1151 omqstat.mq_flags = filp->f_flags & O_NONBLOCK; 1156 omqstat.mq_flags = filp->f_flags & O_NONBLOCK;
1152 if (u_mqstat) { 1157 if (u_mqstat) {
1153 ret = audit_mq_getsetattr(mqdes, &mqstat); 1158 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) 1159 if (mqstat.mq_flags & O_NONBLOCK)
1159 filp->f_flags |= O_NONBLOCK; 1160 filp->f_flags |= O_NONBLOCK;
1160 else 1161 else