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 | /** |
