Commit c32c8af43b9adde8d6f938d8e6328c13b8de79ac
1 parent
20114f71b2
Exists in
master
and in
4 other branches
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; }) |
ipc/mqueue.c
... | ... | @@ -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); |
kernel/auditsc.c
... | ... | @@ -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 | /** |