diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2008-12-14 04:02:26 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2009-01-04 15:14:41 -0500 |
commit | 564f6993ffef656aebaf46cf2f1f6cb4f5c97207 (patch) | |
tree | 0bf1ee553ab1241338fe522ffbaed8cd48e10c99 | |
parent | c32c8af43b9adde8d6f938d8e6328c13b8de79ac (diff) |
sanitize audit_mq_open()
* don't bother with allocations
* don't do double copy_from_user()
* don't duplicate parts of check for audit_dummy_context()
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | include/linux/audit.h | 9 | ||||
-rw-r--r-- | ipc/mqueue.c | 23 | ||||
-rw-r--r-- | kernel/auditsc.c | 65 |
3 files changed, 38 insertions, 59 deletions
diff --git a/include/linux/audit.h b/include/linux/audit.h index 67f0cdd991ba..54978bdd2bd4 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h | |||
@@ -450,7 +450,7 @@ extern void audit_socketcall(int nargs, unsigned long *args); | |||
450 | extern int audit_sockaddr(int len, void *addr); | 450 | extern int audit_sockaddr(int len, void *addr); |
451 | extern int __audit_fd_pair(int fd1, int fd2); | 451 | extern int __audit_fd_pair(int fd1, int fd2); |
452 | extern int audit_set_macxattr(const char *name); | 452 | extern int audit_set_macxattr(const char *name); |
453 | extern int __audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr); | 453 | extern void __audit_mq_open(int oflag, mode_t mode, struct mq_attr *attr); |
454 | extern void __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec *abs_timeout); | 454 | extern void __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec *abs_timeout); |
455 | extern void __audit_mq_notify(mqd_t mqdes, const struct sigevent *notification); | 455 | extern void __audit_mq_notify(mqd_t mqdes, const struct sigevent *notification); |
456 | extern void __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat); | 456 | extern void __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat); |
@@ -475,11 +475,10 @@ static inline void audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid | |||
475 | if (unlikely(!audit_dummy_context())) | 475 | if (unlikely(!audit_dummy_context())) |
476 | __audit_ipc_set_perm(qbytes, uid, gid, mode); | 476 | __audit_ipc_set_perm(qbytes, uid, gid, mode); |
477 | } | 477 | } |
478 | static inline int audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr) | 478 | static inline void audit_mq_open(int oflag, mode_t mode, struct mq_attr *attr) |
479 | { | 479 | { |
480 | if (unlikely(!audit_dummy_context())) | 480 | if (unlikely(!audit_dummy_context())) |
481 | return __audit_mq_open(oflag, mode, u_attr); | 481 | __audit_mq_open(oflag, mode, attr); |
482 | return 0; | ||
483 | } | 482 | } |
484 | static inline void audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec *abs_timeout) | 483 | static inline void audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec *abs_timeout) |
485 | { | 484 | { |
@@ -541,7 +540,7 @@ extern int audit_signals; | |||
541 | #define audit_fd_pair(n,a) ({ 0; }) | 540 | #define audit_fd_pair(n,a) ({ 0; }) |
542 | #define audit_sockaddr(len, addr) ({ 0; }) | 541 | #define audit_sockaddr(len, addr) ({ 0; }) |
543 | #define audit_set_macxattr(n) do { ; } while (0) | 542 | #define audit_set_macxattr(n) do { ; } while (0) |
544 | #define audit_mq_open(o,m,a) ({ 0; }) | 543 | #define audit_mq_open(o,m,a) ((void)0) |
545 | #define audit_mq_sendrecv(d,l,p,t) ((void)0) | 544 | #define audit_mq_sendrecv(d,l,p,t) ((void)0) |
546 | #define audit_mq_notify(d,n) ((void)0) | 545 | #define audit_mq_notify(d,n) ((void)0) |
547 | #define audit_mq_getsetattr(d,s) ((void)0) | 546 | #define audit_mq_getsetattr(d,s) ((void)0) |
diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 192da806c283..d448b69672b5 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c | |||
@@ -588,22 +588,18 @@ static int mq_attr_ok(struct mq_attr *attr) | |||
588 | * Invoked when creating a new queue via sys_mq_open | 588 | * Invoked when creating a new queue via sys_mq_open |
589 | */ | 589 | */ |
590 | static struct file *do_create(struct dentry *dir, struct dentry *dentry, | 590 | static struct file *do_create(struct dentry *dir, struct dentry *dentry, |
591 | int oflag, mode_t mode, struct mq_attr __user *u_attr) | 591 | int oflag, mode_t mode, struct mq_attr *attr) |
592 | { | 592 | { |
593 | const struct cred *cred = current_cred(); | 593 | const struct cred *cred = current_cred(); |
594 | struct mq_attr attr; | ||
595 | struct file *result; | 594 | struct file *result; |
596 | int ret; | 595 | int ret; |
597 | 596 | ||
598 | if (u_attr) { | 597 | if (attr) { |
599 | ret = -EFAULT; | ||
600 | if (copy_from_user(&attr, u_attr, sizeof(attr))) | ||
601 | goto out; | ||
602 | ret = -EINVAL; | 598 | ret = -EINVAL; |
603 | if (!mq_attr_ok(&attr)) | 599 | if (!mq_attr_ok(attr)) |
604 | goto out; | 600 | goto out; |
605 | /* store for use during create */ | 601 | /* store for use during create */ |
606 | dentry->d_fsdata = &attr; | 602 | dentry->d_fsdata = attr; |
607 | } | 603 | } |
608 | 604 | ||
609 | mode &= ~current->fs->umask; | 605 | mode &= ~current->fs->umask; |
@@ -660,11 +656,13 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, | |||
660 | struct dentry *dentry; | 656 | struct dentry *dentry; |
661 | struct file *filp; | 657 | struct file *filp; |
662 | char *name; | 658 | char *name; |
659 | struct mq_attr attr; | ||
663 | int fd, error; | 660 | int fd, error; |
664 | 661 | ||
665 | error = audit_mq_open(oflag, mode, u_attr); | 662 | if (u_attr && copy_from_user(&attr, u_attr, sizeof(struct mq_attr))) |
666 | if (error != 0) | 663 | return -EFAULT; |
667 | return error; | 664 | |
665 | audit_mq_open(oflag, mode, u_attr ? &attr : NULL); | ||
668 | 666 | ||
669 | if (IS_ERR(name = getname(u_name))) | 667 | if (IS_ERR(name = getname(u_name))) |
670 | return PTR_ERR(name); | 668 | return PTR_ERR(name); |
@@ -690,7 +688,8 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, | |||
690 | filp = do_open(dentry, oflag); | 688 | filp = do_open(dentry, oflag); |
691 | } else { | 689 | } else { |
692 | filp = do_create(mqueue_mnt->mnt_root, dentry, | 690 | filp = do_create(mqueue_mnt->mnt_root, dentry, |
693 | oflag, mode, u_attr); | 691 | oflag, mode, |
692 | u_attr ? &attr : NULL); | ||
694 | } | 693 | } |
695 | } else { | 694 | } else { |
696 | error = -ENOENT; | 695 | error = -ENOENT; |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 140c47453470..83e946f1cdde 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -124,13 +124,6 @@ struct audit_aux_data { | |||
124 | /* Number of target pids per aux struct. */ | 124 | /* Number of target pids per aux struct. */ |
125 | #define AUDIT_AUX_PIDS 16 | 125 | #define AUDIT_AUX_PIDS 16 |
126 | 126 | ||
127 | struct audit_aux_data_mq_open { | ||
128 | struct audit_aux_data d; | ||
129 | int oflag; | ||
130 | mode_t mode; | ||
131 | struct mq_attr attr; | ||
132 | }; | ||
133 | |||
134 | struct audit_aux_data_execve { | 127 | struct audit_aux_data_execve { |
135 | struct audit_aux_data d; | 128 | struct audit_aux_data d; |
136 | int argc; | 129 | int argc; |
@@ -242,6 +235,11 @@ struct audit_context { | |||
242 | unsigned int msg_prio; | 235 | unsigned int msg_prio; |
243 | struct timespec abs_timeout; | 236 | struct timespec abs_timeout; |
244 | } mq_sendrecv; | 237 | } mq_sendrecv; |
238 | struct { | ||
239 | int oflag; | ||
240 | mode_t mode; | ||
241 | struct mq_attr attr; | ||
242 | } mq_open; | ||
245 | }; | 243 | }; |
246 | 244 | ||
247 | #if AUDIT_DEBUG | 245 | #if AUDIT_DEBUG |
@@ -1263,6 +1261,16 @@ static void show_special(struct audit_context *context, int *call_panic) | |||
1263 | return; | 1261 | return; |
1264 | } | 1262 | } |
1265 | break; } | 1263 | break; } |
1264 | case AUDIT_MQ_OPEN: { | ||
1265 | audit_log_format(ab, | ||
1266 | "oflag=0x%x mode=%#o mq_flags=0x%lx mq_maxmsg=%ld " | ||
1267 | "mq_msgsize=%ld mq_curmsgs=%ld", | ||
1268 | context->mq_open.oflag, context->mq_open.mode, | ||
1269 | context->mq_open.attr.mq_flags, | ||
1270 | context->mq_open.attr.mq_maxmsg, | ||
1271 | context->mq_open.attr.mq_msgsize, | ||
1272 | context->mq_open.attr.mq_curmsgs); | ||
1273 | break; } | ||
1266 | case AUDIT_MQ_SENDRECV: { | 1274 | case AUDIT_MQ_SENDRECV: { |
1267 | audit_log_format(ab, | 1275 | audit_log_format(ab, |
1268 | "mqdes=%d msg_len=%zd msg_prio=%u " | 1276 | "mqdes=%d msg_len=%zd msg_prio=%u " |
@@ -1368,15 +1376,6 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
1368 | continue; /* audit_panic has been called */ | 1376 | continue; /* audit_panic has been called */ |
1369 | 1377 | ||
1370 | switch (aux->type) { | 1378 | switch (aux->type) { |
1371 | case AUDIT_MQ_OPEN: { | ||
1372 | struct audit_aux_data_mq_open *axi = (void *)aux; | ||
1373 | audit_log_format(ab, | ||
1374 | "oflag=0x%x mode=%#o mq_flags=0x%lx mq_maxmsg=%ld " | ||
1375 | "mq_msgsize=%ld mq_curmsgs=%ld", | ||
1376 | axi->oflag, axi->mode, axi->attr.mq_flags, | ||
1377 | axi->attr.mq_maxmsg, axi->attr.mq_msgsize, | ||
1378 | axi->attr.mq_curmsgs); | ||
1379 | break; } | ||
1380 | 1379 | ||
1381 | case AUDIT_EXECVE: { | 1380 | case AUDIT_EXECVE: { |
1382 | struct audit_aux_data_execve *axi = (void *)aux; | 1381 | struct audit_aux_data_execve *axi = (void *)aux; |
@@ -2135,38 +2134,20 @@ int audit_set_loginuid(struct task_struct *task, uid_t loginuid) | |||
2135 | * @mode: mode bits | 2134 | * @mode: mode bits |
2136 | * @u_attr: queue attributes | 2135 | * @u_attr: queue attributes |
2137 | * | 2136 | * |
2138 | * Returns 0 for success or NULL context or < 0 on error. | ||
2139 | */ | 2137 | */ |
2140 | int __audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr) | 2138 | void __audit_mq_open(int oflag, mode_t mode, struct mq_attr *attr) |
2141 | { | 2139 | { |
2142 | struct audit_aux_data_mq_open *ax; | ||
2143 | struct audit_context *context = current->audit_context; | 2140 | struct audit_context *context = current->audit_context; |
2144 | 2141 | ||
2145 | if (!audit_enabled) | 2142 | if (attr) |
2146 | return 0; | 2143 | memcpy(&context->mq_open.attr, attr, sizeof(struct mq_attr)); |
2147 | 2144 | else | |
2148 | if (likely(!context)) | 2145 | memset(&context->mq_open.attr, 0, sizeof(struct mq_attr)); |
2149 | return 0; | ||
2150 | |||
2151 | ax = kmalloc(sizeof(*ax), GFP_ATOMIC); | ||
2152 | if (!ax) | ||
2153 | return -ENOMEM; | ||
2154 | |||
2155 | if (u_attr != NULL) { | ||
2156 | if (copy_from_user(&ax->attr, u_attr, sizeof(ax->attr))) { | ||
2157 | kfree(ax); | ||
2158 | return -EFAULT; | ||
2159 | } | ||
2160 | } else | ||
2161 | memset(&ax->attr, 0, sizeof(ax->attr)); | ||
2162 | 2146 | ||
2163 | ax->oflag = oflag; | 2147 | context->mq_open.oflag = oflag; |
2164 | ax->mode = mode; | 2148 | context->mq_open.mode = mode; |
2165 | 2149 | ||
2166 | ax->d.type = AUDIT_MQ_OPEN; | 2150 | context->type = AUDIT_MQ_OPEN; |
2167 | ax->d.next = context->aux; | ||
2168 | context->aux = (void *)ax; | ||
2169 | return 0; | ||
2170 | } | 2151 | } |
2171 | 2152 | ||
2172 | /** | 2153 | /** |