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 | |
| 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')
| -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); |
