aboutsummaryrefslogtreecommitdiffstats
path: root/ipc/mqueue.c
diff options
context:
space:
mode:
Diffstat (limited to 'ipc/mqueue.c')
-rw-r--r--ipc/mqueue.c54
1 files changed, 30 insertions, 24 deletions
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index e7b2f68f8d77..192da806c283 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -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
@@ -829,17 +825,22 @@ asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr,
829 struct ext_wait_queue *receiver; 825 struct ext_wait_queue *receiver;
830 struct msg_msg *msg_ptr; 826 struct msg_msg *msg_ptr;
831 struct mqueue_inode_info *info; 827 struct mqueue_inode_info *info;
828 struct timespec ts, *p = NULL;
832 long timeout; 829 long timeout;
833 int ret; 830 int ret;
834 831
835 ret = audit_mq_timedsend(mqdes, msg_len, msg_prio, u_abs_timeout); 832 if (u_abs_timeout) {
836 if (ret != 0) 833 if (copy_from_user(&ts, u_abs_timeout,
837 return ret; 834 sizeof(struct timespec)))
835 return -EFAULT;
836 p = &ts;
837 }
838 838
839 if (unlikely(msg_prio >= (unsigned long) MQ_PRIO_MAX)) 839 if (unlikely(msg_prio >= (unsigned long) MQ_PRIO_MAX))
840 return -EINVAL; 840 return -EINVAL;
841 841
842 timeout = prepare_timeout(u_abs_timeout); 842 audit_mq_sendrecv(mqdes, msg_len, msg_prio, p);
843 timeout = prepare_timeout(p);
843 844
844 ret = -EBADF; 845 ret = -EBADF;
845 filp = fget(mqdes); 846 filp = fget(mqdes);
@@ -918,12 +919,17 @@ asmlinkage ssize_t sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr,
918 struct inode *inode; 919 struct inode *inode;
919 struct mqueue_inode_info *info; 920 struct mqueue_inode_info *info;
920 struct ext_wait_queue wait; 921 struct ext_wait_queue wait;
922 struct timespec ts, *p = NULL;
921 923
922 ret = audit_mq_timedreceive(mqdes, msg_len, u_msg_prio, u_abs_timeout); 924 if (u_abs_timeout) {
923 if (ret != 0) 925 if (copy_from_user(&ts, u_abs_timeout,
924 return ret; 926 sizeof(struct timespec)))
927 return -EFAULT;
928 p = &ts;
929 }
925 930
926 timeout = prepare_timeout(u_abs_timeout); 931 audit_mq_sendrecv(mqdes, msg_len, 0, p);
932 timeout = prepare_timeout(p);
927 933
928 ret = -EBADF; 934 ret = -EBADF;
929 filp = fget(mqdes); 935 filp = fget(mqdes);