Commit c32c8af43b9adde8d6f938d8e6328c13b8de79ac

Authored by Al Viro
1 parent 20114f71b2

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>

Showing 3 changed files with 63 additions and 135 deletions Side-by-side Diff

include/linux/audit.h
... ... @@ -451,8 +451,7 @@
451 451 extern int __audit_fd_pair(int fd1, int fd2);
452 452 extern int audit_set_macxattr(const char *name);
453 453 extern int __audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr);
454   -extern int __audit_mq_timedsend(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec __user *u_abs_timeout);
455   -extern int __audit_mq_timedreceive(mqd_t mqdes, size_t msg_len, unsigned int __user *u_msg_prio, const struct timespec __user *u_abs_timeout);
  454 +extern void __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec *abs_timeout);
456 455 extern void __audit_mq_notify(mqd_t mqdes, const struct sigevent *notification);
457 456 extern void __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat);
458 457 extern int __audit_log_bprm_fcaps(struct linux_binprm *bprm,
459 458  
460 459  
... ... @@ -482,18 +481,11 @@
482 481 return __audit_mq_open(oflag, mode, u_attr);
483 482 return 0;
484 483 }
485   -static inline int audit_mq_timedsend(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec __user *u_abs_timeout)
  484 +static inline void audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec *abs_timeout)
486 485 {
487 486 if (unlikely(!audit_dummy_context()))
488   - return __audit_mq_timedsend(mqdes, msg_len, msg_prio, u_abs_timeout);
489   - return 0;
  487 + __audit_mq_sendrecv(mqdes, msg_len, msg_prio, abs_timeout);
490 488 }
491   -static inline int audit_mq_timedreceive(mqd_t mqdes, size_t msg_len, unsigned int __user *u_msg_prio, const struct timespec __user *u_abs_timeout)
492   -{
493   - if (unlikely(!audit_dummy_context()))
494   - return __audit_mq_timedreceive(mqdes, msg_len, u_msg_prio, u_abs_timeout);
495   - return 0;
496   -}
497 489 static inline void audit_mq_notify(mqd_t mqdes, const struct sigevent *notification)
498 490 {
499 491 if (unlikely(!audit_dummy_context()))
... ... @@ -550,8 +542,7 @@
550 542 #define audit_sockaddr(len, addr) ({ 0; })
551 543 #define audit_set_macxattr(n) do { ; } while (0)
552 544 #define audit_mq_open(o,m,a) ({ 0; })
553   -#define audit_mq_timedsend(d,l,p,t) ({ 0; })
554   -#define audit_mq_timedreceive(d,l,p,t) ({ 0; })
  545 +#define audit_mq_sendrecv(d,l,p,t) ((void)0)
555 546 #define audit_mq_notify(d,n) ((void)0)
556 547 #define audit_mq_getsetattr(d,s) ((void)0)
557 548 #define audit_log_bprm_fcaps(b, ncr, ocr) ({ 0; })
... ... @@ -524,31 +524,27 @@
524 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 530 long timeout;
531 531  
532   - if (u_arg) {
533   - if (unlikely(copy_from_user(&ts, u_arg,
534   - sizeof(struct timespec))))
535   - return -EFAULT;
536   -
537   - if (unlikely(ts.tv_nsec < 0 || ts.tv_sec < 0
538   - || ts.tv_nsec >= NSEC_PER_SEC))
  532 + if (p) {
  533 + if (unlikely(p->tv_nsec < 0 || p->tv_sec < 0
  534 + || p->tv_nsec >= NSEC_PER_SEC))
539 535 return -EINVAL;
540 536 nowts = CURRENT_TIME;
541 537 /* first subtract as jiffies can't be too big */
542   - ts.tv_sec -= nowts.tv_sec;
543   - if (ts.tv_nsec < nowts.tv_nsec) {
544   - ts.tv_nsec += NSEC_PER_SEC;
545   - ts.tv_sec--;
  538 + p->tv_sec -= nowts.tv_sec;
  539 + if (p->tv_nsec < nowts.tv_nsec) {
  540 + p->tv_nsec += NSEC_PER_SEC;
  541 + p->tv_sec--;
546 542 }
547   - ts.tv_nsec -= nowts.tv_nsec;
548   - if (ts.tv_sec < 0)
  543 + p->tv_nsec -= nowts.tv_nsec;
  544 + if (p->tv_sec < 0)
549 545 return 0;
550 546  
551   - timeout = timespec_to_jiffies(&ts) + 1;
  547 + timeout = timespec_to_jiffies(p) + 1;
552 548 } else
553 549 return MAX_SCHEDULE_TIMEOUT;
554 550  
555 551  
556 552  
... ... @@ -829,17 +825,22 @@
829 825 struct ext_wait_queue *receiver;
830 826 struct msg_msg *msg_ptr;
831 827 struct mqueue_inode_info *info;
  828 + struct timespec ts, *p = NULL;
832 829 long timeout;
833 830 int ret;
834 831  
835   - ret = audit_mq_timedsend(mqdes, msg_len, msg_prio, u_abs_timeout);
836   - if (ret != 0)
837   - return ret;
  832 + if (u_abs_timeout) {
  833 + if (copy_from_user(&ts, u_abs_timeout,
  834 + sizeof(struct timespec)))
  835 + return -EFAULT;
  836 + p = &ts;
  837 + }
838 838  
839 839 if (unlikely(msg_prio >= (unsigned long) MQ_PRIO_MAX))
840 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 845 ret = -EBADF;
845 846 filp = fget(mqdes);
846 847  
847 848  
... ... @@ -918,12 +919,17 @@
918 919 struct inode *inode;
919 920 struct mqueue_inode_info *info;
920 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);
923   - if (ret != 0)
924   - return ret;
  924 + if (u_abs_timeout) {
  925 + if (copy_from_user(&ts, u_abs_timeout,
  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 934 ret = -EBADF;
929 935 filp = fget(mqdes);
... ... @@ -131,14 +131,6 @@
131 131 struct mq_attr attr;
132 132 };
133 133  
134   -struct audit_aux_data_mq_sendrecv {
135   - struct audit_aux_data d;
136   - mqd_t mqdes;
137   - size_t msg_len;
138   - unsigned int msg_prio;
139   - struct timespec abs_timeout;
140   -};
141   -
142 134 struct audit_aux_data_execve {
143 135 struct audit_aux_data d;
144 136 int argc;
... ... @@ -244,6 +236,12 @@
244 236 mqd_t mqdes;
245 237 int sigev_signo;
246 238 } mq_notify;
  239 + struct {
  240 + mqd_t mqdes;
  241 + size_t msg_len;
  242 + unsigned int msg_prio;
  243 + struct timespec abs_timeout;
  244 + } mq_sendrecv;
247 245 };
248 246  
249 247 #if AUDIT_DEBUG
... ... @@ -1265,6 +1263,16 @@
1265 1263 return;
1266 1264 }
1267 1265 break; }
  1266 + case AUDIT_MQ_SENDRECV: {
  1267 + audit_log_format(ab,
  1268 + "mqdes=%d msg_len=%zd msg_prio=%u "
  1269 + "abs_timeout_sec=%ld abs_timeout_nsec=%ld",
  1270 + context->mq_sendrecv.mqdes,
  1271 + context->mq_sendrecv.msg_len,
  1272 + context->mq_sendrecv.msg_prio,
  1273 + context->mq_sendrecv.abs_timeout.tv_sec,
  1274 + context->mq_sendrecv.abs_timeout.tv_nsec);
  1275 + break; }
1268 1276 case AUDIT_MQ_NOTIFY: {
1269 1277 audit_log_format(ab, "mqdes=%d sigev_signo=%d",
1270 1278 context->mq_notify.mqdes,
... ... @@ -1370,15 +1378,6 @@
1370 1378 axi->attr.mq_curmsgs);
1371 1379 break; }
1372 1380  
1373   - case AUDIT_MQ_SENDRECV: {
1374   - struct audit_aux_data_mq_sendrecv *axi = (void *)aux;
1375   - audit_log_format(ab,
1376   - "mqdes=%d msg_len=%zd msg_prio=%u "
1377   - "abs_timeout_sec=%ld abs_timeout_nsec=%ld",
1378   - axi->mqdes, axi->msg_len, axi->msg_prio,
1379   - axi->abs_timeout.tv_sec, axi->abs_timeout.tv_nsec);
1380   - break; }
1381   -
1382 1381 case AUDIT_EXECVE: {
1383 1382 struct audit_aux_data_execve *axi = (void *)aux;
1384 1383 audit_log_execve_info(context, &ab, axi);
1385 1384  
1386 1385  
1387 1386  
1388 1387  
1389 1388  
1390 1389  
1391 1390  
1392 1391  
... ... @@ -2171,97 +2170,29 @@
2171 2170 }
2172 2171  
2173 2172 /**
2174   - * __audit_mq_timedsend - record audit data for a POSIX MQ timed send
  2173 + * __audit_mq_sendrecv - record audit data for a POSIX MQ timed send/receive
2175 2174 * @mqdes: MQ descriptor
2176 2175 * @msg_len: Message length
2177 2176 * @msg_prio: Message priority
2178   - * @u_abs_timeout: Message timeout in absolute time
  2177 + * @abs_timeout: Message timeout in absolute time
2179 2178 *
2180   - * Returns 0 for success or NULL context or < 0 on error.
2181 2179 */
2182   -int __audit_mq_timedsend(mqd_t mqdes, size_t msg_len, unsigned int msg_prio,
2183   - const struct timespec __user *u_abs_timeout)
  2180 +void __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio,
  2181 + const struct timespec *abs_timeout)
2184 2182 {
2185   - struct audit_aux_data_mq_sendrecv *ax;
2186 2183 struct audit_context *context = current->audit_context;
  2184 + struct timespec *p = &context->mq_sendrecv.abs_timeout;
2187 2185  
2188   - if (!audit_enabled)
2189   - return 0;
  2186 + if (abs_timeout)
  2187 + memcpy(p, abs_timeout, sizeof(struct timespec));
  2188 + else
  2189 + memset(p, 0, sizeof(struct timespec));
2190 2190  
2191   - if (likely(!context))
2192   - return 0;
  2191 + context->mq_sendrecv.mqdes = mqdes;
  2192 + context->mq_sendrecv.msg_len = msg_len;
  2193 + context->mq_sendrecv.msg_prio = msg_prio;
2193 2194  
2194   - ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
2195   - if (!ax)
2196   - return -ENOMEM;
2197   -
2198   - if (u_abs_timeout != NULL) {
2199   - if (copy_from_user(&ax->abs_timeout, u_abs_timeout, sizeof(ax->abs_timeout))) {
2200   - kfree(ax);
2201   - return -EFAULT;
2202   - }
2203   - } else
2204   - memset(&ax->abs_timeout, 0, sizeof(ax->abs_timeout));
2205   -
2206   - ax->mqdes = mqdes;
2207   - ax->msg_len = msg_len;
2208   - ax->msg_prio = msg_prio;
2209   -
2210   - ax->d.type = AUDIT_MQ_SENDRECV;
2211   - ax->d.next = context->aux;
2212   - context->aux = (void *)ax;
2213   - return 0;
2214   -}
2215   -
2216   -/**
2217   - * __audit_mq_timedreceive - record audit data for a POSIX MQ timed receive
2218   - * @mqdes: MQ descriptor
2219   - * @msg_len: Message length
2220   - * @u_msg_prio: Message priority
2221   - * @u_abs_timeout: Message timeout in absolute time
2222   - *
2223   - * Returns 0 for success or NULL context or < 0 on error.
2224   - */
2225   -int __audit_mq_timedreceive(mqd_t mqdes, size_t msg_len,
2226   - unsigned int __user *u_msg_prio,
2227   - const struct timespec __user *u_abs_timeout)
2228   -{
2229   - struct audit_aux_data_mq_sendrecv *ax;
2230   - struct audit_context *context = current->audit_context;
2231   -
2232   - if (!audit_enabled)
2233   - return 0;
2234   -
2235   - if (likely(!context))
2236   - return 0;
2237   -
2238   - ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
2239   - if (!ax)
2240   - return -ENOMEM;
2241   -
2242   - if (u_msg_prio != NULL) {
2243   - if (get_user(ax->msg_prio, u_msg_prio)) {
2244   - kfree(ax);
2245   - return -EFAULT;
2246   - }
2247   - } else
2248   - ax->msg_prio = 0;
2249   -
2250   - if (u_abs_timeout != NULL) {
2251   - if (copy_from_user(&ax->abs_timeout, u_abs_timeout, sizeof(ax->abs_timeout))) {
2252   - kfree(ax);
2253   - return -EFAULT;
2254   - }
2255   - } else
2256   - memset(&ax->abs_timeout, 0, sizeof(ax->abs_timeout));
2257   -
2258   - ax->mqdes = mqdes;
2259   - ax->msg_len = msg_len;
2260   -
2261   - ax->d.type = AUDIT_MQ_SENDRECV;
2262   - ax->d.next = context->aux;
2263   - context->aux = (void *)ax;
2264   - return 0;
  2195 + context->type = AUDIT_MQ_SENDRECV;
2265 2196 }
2266 2197  
2267 2198 /**