diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2008-12-14 03:46:48 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2009-01-04 15:14:40 -0500 |
commit | c32c8af43b9adde8d6f938d8e6328c13b8de79ac (patch) | |
tree | 6377079bba7530d2aa8a688ebf9ba3e09ae085a7 /ipc/mqueue.c | |
parent | 20114f71b27cafeb7c7e41d2b0f0b68c3fbb022b (diff) |
sanitize AUDIT_MQ_SENDRECV
* logging the original value of *msg_prio in mq_timedreceive(2)
is insane - the argument is write-only (i.e. syscall always
ignores the original value and only overwrites it).
* merge __audit_mq_timed{send,receive}
* don't do copy_from_user() twice
* don't mess with allocations in auditsc part
* ... and don't bother checking !audit_enabled and !context in there -
we'd already checked for audit_dummy_context().
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'ipc/mqueue.c')
-rw-r--r-- | ipc/mqueue.c | 54 |
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 | ||
527 | static long prepare_timeout(const struct timespec __user *u_arg) | 527 | static 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); |