Commit 073115d6b29c7910feaa08241c6484637f5ca958
Committed by
Al Viro
1 parent
ce29b682e2
Exists in
master
and in
4 other branches
[PATCH] Rework of IPC auditing
1) The audit_ipc_perms() function has been split into two different functions: - audit_ipc_obj() - audit_ipc_set_perm() There's a key shift here... The audit_ipc_obj() collects the uid, gid, mode, and SElinux context label of the current ipc object. This audit_ipc_obj() hook is now found in several places. Most notably, it is hooked in ipcperms(), which is called in various places around the ipc code permforming a MAC check. Additionally there are several places where *checkid() is used to validate that an operation is being performed on a valid object while not necessarily having a nearby ipcperms() call. In these locations, audit_ipc_obj() is called to ensure that the information is captured by the audit system. The audit_set_new_perm() function is called any time the permissions on the ipc object changes. In this case, the NEW permissions are recorded (and note that an audit_ipc_obj() call exists just a few lines before each instance). 2) Support for an AUDIT_IPC_SET_PERM audit message type. This allows for separate auxiliary audit records for normal operations on an IPC object and permissions changes. Note that the same struct audit_aux_data_ipcctl is used and populated, however there are separate audit_log_format statements based on the type of the message. Finally, the AUDIT_IPC block of code in audit_free_aux() was extended to handle aux messages of this new type. No more mem leaks I hope ;-) Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Showing 6 changed files with 98 additions and 11 deletions Side-by-side Diff
include/linux/audit.h
... | ... | @@ -83,6 +83,7 @@ |
83 | 83 | #define AUDIT_CONFIG_CHANGE 1305 /* Audit system configuration change */ |
84 | 84 | #define AUDIT_SOCKADDR 1306 /* sockaddr copied as syscall arg */ |
85 | 85 | #define AUDIT_CWD 1307 /* Current working directory */ |
86 | +#define AUDIT_IPC_SET_PERM 1311 /* IPC new permissions record type */ | |
86 | 87 | |
87 | 88 | #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ |
88 | 89 | #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ |
... | ... | @@ -319,7 +320,8 @@ |
319 | 320 | struct timespec *t, unsigned int *serial); |
320 | 321 | extern int audit_set_loginuid(struct task_struct *task, uid_t loginuid); |
321 | 322 | extern uid_t audit_get_loginuid(struct audit_context *ctx); |
322 | -extern int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode, struct kern_ipc_perm *ipcp); | |
323 | +extern int audit_ipc_obj(struct kern_ipc_perm *ipcp); | |
324 | +extern int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode, struct kern_ipc_perm *ipcp); | |
323 | 325 | extern int audit_socketcall(int nargs, unsigned long *args); |
324 | 326 | extern int audit_sockaddr(int len, void *addr); |
325 | 327 | extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt); |
... | ... | @@ -338,7 +340,8 @@ |
338 | 340 | #define audit_inode_child(d,i,p) do { ; } while (0) |
339 | 341 | #define auditsc_get_stamp(c,t,s) do { BUG(); } while (0) |
340 | 342 | #define audit_get_loginuid(c) ({ -1; }) |
341 | -#define audit_ipc_perms(q,u,g,m,i) ({ 0; }) | |
343 | +#define audit_ipc_obj(i) ({ 0; }) | |
344 | +#define audit_ipc_set_perm(q,u,g,m,i) ({ 0; }) | |
342 | 345 | #define audit_socketcall(n,a) ({ 0; }) |
343 | 346 | #define audit_sockaddr(len, addr) ({ 0; }) |
344 | 347 | #define audit_avc_path(dentry, mnt) ({ 0; }) |
ipc/msg.c
... | ... | @@ -13,6 +13,9 @@ |
13 | 13 | * mostly rewritten, threaded and wake-one semantics added |
14 | 14 | * MSGMAX limit removed, sysctl's added |
15 | 15 | * (c) 1999 Manfred Spraul <manfred@colorfullife.com> |
16 | + * | |
17 | + * support for audit of ipc object properties and permission changes | |
18 | + * Dustin Kirkland <dustin.kirkland@us.ibm.com> | |
16 | 19 | */ |
17 | 20 | |
18 | 21 | #include <linux/capability.h> |
... | ... | @@ -447,6 +450,11 @@ |
447 | 450 | if (msg_checkid(msq,msqid)) |
448 | 451 | goto out_unlock_up; |
449 | 452 | ipcp = &msq->q_perm; |
453 | + | |
454 | + err = audit_ipc_obj(ipcp); | |
455 | + if (err) | |
456 | + goto out_unlock_up; | |
457 | + | |
450 | 458 | err = -EPERM; |
451 | 459 | if (current->euid != ipcp->cuid && |
452 | 460 | current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN)) |
... | ... | @@ -460,7 +468,8 @@ |
460 | 468 | switch (cmd) { |
461 | 469 | case IPC_SET: |
462 | 470 | { |
463 | - if ((err = audit_ipc_perms(setbuf.qbytes, setbuf.uid, setbuf.gid, setbuf.mode, ipcp))) | |
471 | + err = audit_ipc_set_perm(setbuf.qbytes, setbuf.uid, setbuf.gid, setbuf.mode, ipcp); | |
472 | + if (err) | |
464 | 473 | goto out_unlock_up; |
465 | 474 | |
466 | 475 | err = -EPERM; |
ipc/sem.c
... | ... | @@ -61,6 +61,9 @@ |
61 | 61 | * (c) 2001 Red Hat Inc <alan@redhat.com> |
62 | 62 | * Lockless wakeup |
63 | 63 | * (c) 2003 Manfred Spraul <manfred@colorfullife.com> |
64 | + * | |
65 | + * support for audit of ipc object properties and permission changes | |
66 | + * Dustin Kirkland <dustin.kirkland@us.ibm.com> | |
64 | 67 | */ |
65 | 68 | |
66 | 69 | #include <linux/config.h> |
... | ... | @@ -820,6 +823,11 @@ |
820 | 823 | goto out_unlock; |
821 | 824 | } |
822 | 825 | ipcp = &sma->sem_perm; |
826 | + | |
827 | + err = audit_ipc_obj(ipcp); | |
828 | + if (err) | |
829 | + goto out_unlock; | |
830 | + | |
823 | 831 | if (current->euid != ipcp->cuid && |
824 | 832 | current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN)) { |
825 | 833 | err=-EPERM; |
... | ... | @@ -836,7 +844,8 @@ |
836 | 844 | err = 0; |
837 | 845 | break; |
838 | 846 | case IPC_SET: |
839 | - if ((err = audit_ipc_perms(0, setbuf.uid, setbuf.gid, setbuf.mode, ipcp))) | |
847 | + err = audit_ipc_set_perm(0, setbuf.uid, setbuf.gid, setbuf.mode, ipcp); | |
848 | + if (err) | |
840 | 849 | goto out_unlock; |
841 | 850 | ipcp->uid = setbuf.uid; |
842 | 851 | ipcp->gid = setbuf.gid; |
ipc/shm.c
... | ... | @@ -13,6 +13,8 @@ |
13 | 13 | * Shared /dev/zero support, Kanoj Sarcar <kanoj@sgi.com> |
14 | 14 | * Move the mm functionality over to mm/shmem.c, Christoph Rohland <cr@sap.com> |
15 | 15 | * |
16 | + * support for audit of ipc object properties and permission changes | |
17 | + * Dustin Kirkland <dustin.kirkland@us.ibm.com> | |
16 | 18 | */ |
17 | 19 | |
18 | 20 | #include <linux/config.h> |
... | ... | @@ -542,6 +544,10 @@ |
542 | 544 | if(err) |
543 | 545 | goto out_unlock; |
544 | 546 | |
547 | + err = audit_ipc_obj(&(shp->shm_perm)); | |
548 | + if (err) | |
549 | + goto out_unlock; | |
550 | + | |
545 | 551 | if (!capable(CAP_IPC_LOCK)) { |
546 | 552 | err = -EPERM; |
547 | 553 | if (current->euid != shp->shm_perm.uid && |
... | ... | @@ -594,6 +600,10 @@ |
594 | 600 | if(err) |
595 | 601 | goto out_unlock_up; |
596 | 602 | |
603 | + err = audit_ipc_obj(&(shp->shm_perm)); | |
604 | + if (err) | |
605 | + goto out_unlock_up; | |
606 | + | |
597 | 607 | if (current->euid != shp->shm_perm.uid && |
598 | 608 | current->euid != shp->shm_perm.cuid && |
599 | 609 | !capable(CAP_SYS_ADMIN)) { |
600 | 610 | |
... | ... | @@ -627,11 +637,14 @@ |
627 | 637 | err=-EINVAL; |
628 | 638 | if(shp==NULL) |
629 | 639 | goto out_up; |
630 | - if ((err = audit_ipc_perms(0, setbuf.uid, setbuf.gid, | |
631 | - setbuf.mode, &(shp->shm_perm)))) | |
632 | - goto out_unlock_up; | |
633 | 640 | err = shm_checkid(shp,shmid); |
634 | 641 | if(err) |
642 | + goto out_unlock_up; | |
643 | + err = audit_ipc_obj(&(shp->shm_perm)); | |
644 | + if (err) | |
645 | + goto out_unlock_up; | |
646 | + err = audit_ipc_set_perm(0, setbuf.uid, setbuf.gid, setbuf.mode, &(shp->shm_perm)); | |
647 | + if (err) | |
635 | 648 | goto out_unlock_up; |
636 | 649 | err=-EPERM; |
637 | 650 | if (current->euid != shp->shm_perm.uid && |
ipc/util.c
... | ... | @@ -10,6 +10,8 @@ |
10 | 10 | * Manfred Spraul <manfred@colorfullife.com> |
11 | 11 | * Oct 2002 - One lock per IPC id. RCU ipc_free for lock-free grow_ary(). |
12 | 12 | * Mingming Cao <cmm@us.ibm.com> |
13 | + * Mar 2006 - support for audit of ipc object properties | |
14 | + * Dustin Kirkland <dustin.kirkland@us.ibm.com> | |
13 | 15 | */ |
14 | 16 | |
15 | 17 | #include <linux/config.h> |
... | ... | @@ -27,6 +29,7 @@ |
27 | 29 | #include <linux/workqueue.h> |
28 | 30 | #include <linux/seq_file.h> |
29 | 31 | #include <linux/proc_fs.h> |
32 | +#include <linux/audit.h> | |
30 | 33 | |
31 | 34 | #include <asm/unistd.h> |
32 | 35 | |
33 | 36 | |
... | ... | @@ -464,8 +467,10 @@ |
464 | 467 | |
465 | 468 | int ipcperms (struct kern_ipc_perm *ipcp, short flag) |
466 | 469 | { /* flag will most probably be 0 or S_...UGO from <linux/stat.h> */ |
467 | - int requested_mode, granted_mode; | |
470 | + int requested_mode, granted_mode, err; | |
468 | 471 | |
472 | + if (unlikely((err = audit_ipc_obj(ipcp)))) | |
473 | + return err; | |
469 | 474 | requested_mode = (flag >> 6) | (flag >> 3) | flag; |
470 | 475 | granted_mode = ipcp->mode; |
471 | 476 | if (current->euid == ipcp->cuid || current->euid == ipcp->uid) |
kernel/auditsc.c
... | ... | @@ -646,6 +646,25 @@ |
646 | 646 | } |
647 | 647 | break; } |
648 | 648 | |
649 | + case AUDIT_IPC_SET_PERM: { | |
650 | + struct audit_aux_data_ipcctl *axi = (void *)aux; | |
651 | + audit_log_format(ab, | |
652 | + " new qbytes=%lx new iuid=%u new igid=%u new mode=%x", | |
653 | + axi->qbytes, axi->uid, axi->gid, axi->mode); | |
654 | + if (axi->osid != 0) { | |
655 | + char *ctx = NULL; | |
656 | + u32 len; | |
657 | + if (selinux_ctxid_to_string( | |
658 | + axi->osid, &ctx, &len)) { | |
659 | + audit_log_format(ab, " osid=%u", | |
660 | + axi->osid); | |
661 | + call_panic = 1; | |
662 | + } else | |
663 | + audit_log_format(ab, " obj=%s", ctx); | |
664 | + kfree(ctx); | |
665 | + } | |
666 | + break; } | |
667 | + | |
649 | 668 | case AUDIT_SOCKETCALL: { |
650 | 669 | int i; |
651 | 670 | struct audit_aux_data_socketcall *axs = (void *)aux; |
... | ... | @@ -1148,7 +1167,36 @@ |
1148 | 1167 | } |
1149 | 1168 | |
1150 | 1169 | /** |
1151 | - * audit_ipc_perms - record audit data for ipc | |
1170 | + * audit_ipc_obj - record audit data for ipc object | |
1171 | + * @ipcp: ipc permissions | |
1172 | + * | |
1173 | + * Returns 0 for success or NULL context or < 0 on error. | |
1174 | + */ | |
1175 | +int audit_ipc_obj(struct kern_ipc_perm *ipcp) | |
1176 | +{ | |
1177 | + struct audit_aux_data_ipcctl *ax; | |
1178 | + struct audit_context *context = current->audit_context; | |
1179 | + | |
1180 | + if (likely(!context)) | |
1181 | + return 0; | |
1182 | + | |
1183 | + ax = kmalloc(sizeof(*ax), GFP_ATOMIC); | |
1184 | + if (!ax) | |
1185 | + return -ENOMEM; | |
1186 | + | |
1187 | + ax->uid = ipcp->uid; | |
1188 | + ax->gid = ipcp->gid; | |
1189 | + ax->mode = ipcp->mode; | |
1190 | + selinux_get_ipc_sid(ipcp, &ax->osid); | |
1191 | + | |
1192 | + ax->d.type = AUDIT_IPC; | |
1193 | + ax->d.next = context->aux; | |
1194 | + context->aux = (void *)ax; | |
1195 | + return 0; | |
1196 | +} | |
1197 | + | |
1198 | +/** | |
1199 | + * audit_ipc_set_perm - record audit data for new ipc permissions | |
1152 | 1200 | * @qbytes: msgq bytes |
1153 | 1201 | * @uid: msgq user id |
1154 | 1202 | * @gid: msgq group id |
... | ... | @@ -1156,7 +1204,7 @@ |
1156 | 1204 | * |
1157 | 1205 | * Returns 0 for success or NULL context or < 0 on error. |
1158 | 1206 | */ |
1159 | -int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode, struct kern_ipc_perm *ipcp) | |
1207 | +int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode, struct kern_ipc_perm *ipcp) | |
1160 | 1208 | { |
1161 | 1209 | struct audit_aux_data_ipcctl *ax; |
1162 | 1210 | struct audit_context *context = current->audit_context; |
... | ... | @@ -1174,7 +1222,7 @@ |
1174 | 1222 | ax->mode = mode; |
1175 | 1223 | selinux_get_ipc_sid(ipcp, &ax->osid); |
1176 | 1224 | |
1177 | - ax->d.type = AUDIT_IPC; | |
1225 | + ax->d.type = AUDIT_IPC_SET_PERM; | |
1178 | 1226 | ax->d.next = context->aux; |
1179 | 1227 | context->aux = (void *)ax; |
1180 | 1228 | return 0; |