aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve Grubb <sgrubb@redhat.com>2006-04-02 17:07:33 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2006-05-01 06:10:04 -0400
commit073115d6b29c7910feaa08241c6484637f5ca958 (patch)
tree5fd32da9f54b3c12b65d3c0142fb9bdf87dc01c3
parentce29b682e228c70cdc91a1b2935c5adb2087bab8 (diff)
[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>
-rw-r--r--include/linux/audit.h7
-rw-r--r--ipc/msg.c11
-rw-r--r--ipc/sem.c11
-rw-r--r--ipc/shm.c19
-rw-r--r--ipc/util.c7
-rw-r--r--kernel/auditsc.c54
6 files changed, 98 insertions, 11 deletions
diff --git a/include/linux/audit.h b/include/linux/audit.h
index d5c40823e166..b74c148f14e3 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -83,6 +83,7 @@
83#define AUDIT_CONFIG_CHANGE 1305 /* Audit system configuration change */ 83#define AUDIT_CONFIG_CHANGE 1305 /* Audit system configuration change */
84#define AUDIT_SOCKADDR 1306 /* sockaddr copied as syscall arg */ 84#define AUDIT_SOCKADDR 1306 /* sockaddr copied as syscall arg */
85#define AUDIT_CWD 1307 /* Current working directory */ 85#define AUDIT_CWD 1307 /* Current working directory */
86#define AUDIT_IPC_SET_PERM 1311 /* IPC new permissions record type */
86 87
87#define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ 88#define AUDIT_AVC 1400 /* SE Linux avc denial or grant */
88#define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ 89#define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */
@@ -319,7 +320,8 @@ extern void auditsc_get_stamp(struct audit_context *ctx,
319 struct timespec *t, unsigned int *serial); 320 struct timespec *t, unsigned int *serial);
320extern int audit_set_loginuid(struct task_struct *task, uid_t loginuid); 321extern int audit_set_loginuid(struct task_struct *task, uid_t loginuid);
321extern uid_t audit_get_loginuid(struct audit_context *ctx); 322extern uid_t audit_get_loginuid(struct audit_context *ctx);
322extern int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode, struct kern_ipc_perm *ipcp); 323extern int audit_ipc_obj(struct kern_ipc_perm *ipcp);
324extern int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode, struct kern_ipc_perm *ipcp);
323extern int audit_socketcall(int nargs, unsigned long *args); 325extern int audit_socketcall(int nargs, unsigned long *args);
324extern int audit_sockaddr(int len, void *addr); 326extern int audit_sockaddr(int len, void *addr);
325extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt); 327extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt);
@@ -338,7 +340,8 @@ extern int audit_set_macxattr(const char *name);
338#define audit_inode_child(d,i,p) do { ; } while (0) 340#define audit_inode_child(d,i,p) do { ; } while (0)
339#define auditsc_get_stamp(c,t,s) do { BUG(); } while (0) 341#define auditsc_get_stamp(c,t,s) do { BUG(); } while (0)
340#define audit_get_loginuid(c) ({ -1; }) 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#define audit_socketcall(n,a) ({ 0; }) 345#define audit_socketcall(n,a) ({ 0; })
343#define audit_sockaddr(len, addr) ({ 0; }) 346#define audit_sockaddr(len, addr) ({ 0; })
344#define audit_avc_path(dentry, mnt) ({ 0; }) 347#define audit_avc_path(dentry, mnt) ({ 0; })
diff --git a/ipc/msg.c b/ipc/msg.c
index 48a7f17a7236..7d1340ccb16b 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -13,6 +13,9 @@
13 * mostly rewritten, threaded and wake-one semantics added 13 * mostly rewritten, threaded and wake-one semantics added
14 * MSGMAX limit removed, sysctl's added 14 * MSGMAX limit removed, sysctl's added
15 * (c) 1999 Manfred Spraul <manfred@colorfullife.com> 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#include <linux/capability.h> 21#include <linux/capability.h>
@@ -447,6 +450,11 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf)
447 if (msg_checkid(msq,msqid)) 450 if (msg_checkid(msq,msqid))
448 goto out_unlock_up; 451 goto out_unlock_up;
449 ipcp = &msq->q_perm; 452 ipcp = &msq->q_perm;
453
454 err = audit_ipc_obj(ipcp);
455 if (err)
456 goto out_unlock_up;
457
450 err = -EPERM; 458 err = -EPERM;
451 if (current->euid != ipcp->cuid && 459 if (current->euid != ipcp->cuid &&
452 current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN)) 460 current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN))
@@ -460,7 +468,8 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf)
460 switch (cmd) { 468 switch (cmd) {
461 case IPC_SET: 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 goto out_unlock_up; 473 goto out_unlock_up;
465 474
466 err = -EPERM; 475 err = -EPERM;
diff --git a/ipc/sem.c b/ipc/sem.c
index 642659cd596b..7919f8ece6ba 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -61,6 +61,9 @@
61 * (c) 2001 Red Hat Inc <alan@redhat.com> 61 * (c) 2001 Red Hat Inc <alan@redhat.com>
62 * Lockless wakeup 62 * Lockless wakeup
63 * (c) 2003 Manfred Spraul <manfred@colorfullife.com> 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#include <linux/config.h> 69#include <linux/config.h>
@@ -820,6 +823,11 @@ static int semctl_down(int semid, int semnum, int cmd, int version, union semun
820 goto out_unlock; 823 goto out_unlock;
821 } 824 }
822 ipcp = &sma->sem_perm; 825 ipcp = &sma->sem_perm;
826
827 err = audit_ipc_obj(ipcp);
828 if (err)
829 goto out_unlock;
830
823 if (current->euid != ipcp->cuid && 831 if (current->euid != ipcp->cuid &&
824 current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN)) { 832 current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN)) {
825 err=-EPERM; 833 err=-EPERM;
@@ -836,7 +844,8 @@ static int semctl_down(int semid, int semnum, int cmd, int version, union semun
836 err = 0; 844 err = 0;
837 break; 845 break;
838 case IPC_SET: 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 goto out_unlock; 849 goto out_unlock;
841 ipcp->uid = setbuf.uid; 850 ipcp->uid = setbuf.uid;
842 ipcp->gid = setbuf.gid; 851 ipcp->gid = setbuf.gid;
diff --git a/ipc/shm.c b/ipc/shm.c
index 1c2faf62bc73..809896851902 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -13,6 +13,8 @@
13 * Shared /dev/zero support, Kanoj Sarcar <kanoj@sgi.com> 13 * Shared /dev/zero support, Kanoj Sarcar <kanoj@sgi.com>
14 * Move the mm functionality over to mm/shmem.c, Christoph Rohland <cr@sap.com> 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#include <linux/config.h> 20#include <linux/config.h>
@@ -542,6 +544,10 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
542 if(err) 544 if(err)
543 goto out_unlock; 545 goto out_unlock;
544 546
547 err = audit_ipc_obj(&(shp->shm_perm));
548 if (err)
549 goto out_unlock;
550
545 if (!capable(CAP_IPC_LOCK)) { 551 if (!capable(CAP_IPC_LOCK)) {
546 err = -EPERM; 552 err = -EPERM;
547 if (current->euid != shp->shm_perm.uid && 553 if (current->euid != shp->shm_perm.uid &&
@@ -594,6 +600,10 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
594 if(err) 600 if(err)
595 goto out_unlock_up; 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 if (current->euid != shp->shm_perm.uid && 607 if (current->euid != shp->shm_perm.uid &&
598 current->euid != shp->shm_perm.cuid && 608 current->euid != shp->shm_perm.cuid &&
599 !capable(CAP_SYS_ADMIN)) { 609 !capable(CAP_SYS_ADMIN)) {
@@ -627,12 +637,15 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
627 err=-EINVAL; 637 err=-EINVAL;
628 if(shp==NULL) 638 if(shp==NULL)
629 goto out_up; 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 err = shm_checkid(shp,shmid); 640 err = shm_checkid(shp,shmid);
634 if(err) 641 if(err)
635 goto out_unlock_up; 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)
648 goto out_unlock_up;
636 err=-EPERM; 649 err=-EPERM;
637 if (current->euid != shp->shm_perm.uid && 650 if (current->euid != shp->shm_perm.uid &&
638 current->euid != shp->shm_perm.cuid && 651 current->euid != shp->shm_perm.cuid &&
diff --git a/ipc/util.c b/ipc/util.c
index b3dcfad3b4f7..8193299f45f6 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -10,6 +10,8 @@
10 * Manfred Spraul <manfred@colorfullife.com> 10 * Manfred Spraul <manfred@colorfullife.com>
11 * Oct 2002 - One lock per IPC id. RCU ipc_free for lock-free grow_ary(). 11 * Oct 2002 - One lock per IPC id. RCU ipc_free for lock-free grow_ary().
12 * Mingming Cao <cmm@us.ibm.com> 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#include <linux/config.h> 17#include <linux/config.h>
@@ -27,6 +29,7 @@
27#include <linux/workqueue.h> 29#include <linux/workqueue.h>
28#include <linux/seq_file.h> 30#include <linux/seq_file.h>
29#include <linux/proc_fs.h> 31#include <linux/proc_fs.h>
32#include <linux/audit.h>
30 33
31#include <asm/unistd.h> 34#include <asm/unistd.h>
32 35
@@ -464,8 +467,10 @@ void ipc_rcu_putref(void *ptr)
464 467
465int ipcperms (struct kern_ipc_perm *ipcp, short flag) 468int ipcperms (struct kern_ipc_perm *ipcp, short flag)
466{ /* flag will most probably be 0 or S_...UGO from <linux/stat.h> */ 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 requested_mode = (flag >> 6) | (flag >> 3) | flag; 474 requested_mode = (flag >> 6) | (flag >> 3) | flag;
470 granted_mode = ipcp->mode; 475 granted_mode = ipcp->mode;
471 if (current->euid == ipcp->cuid || current->euid == ipcp->uid) 476 if (current->euid == ipcp->cuid || current->euid == ipcp->uid)
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index d94e0404113c..a300736ee037 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -646,6 +646,25 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
646 } 646 }
647 break; } 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 case AUDIT_SOCKETCALL: { 668 case AUDIT_SOCKETCALL: {
650 int i; 669 int i;
651 struct audit_aux_data_socketcall *axs = (void *)aux; 670 struct audit_aux_data_socketcall *axs = (void *)aux;
@@ -1148,7 +1167,36 @@ uid_t audit_get_loginuid(struct audit_context *ctx)
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 */
1175int 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 * @qbytes: msgq bytes 1200 * @qbytes: msgq bytes
1153 * @uid: msgq user id 1201 * @uid: msgq user id
1154 * @gid: msgq group id 1202 * @gid: msgq group id
@@ -1156,7 +1204,7 @@ uid_t audit_get_loginuid(struct audit_context *ctx)
1156 * 1204 *
1157 * Returns 0 for success or NULL context or < 0 on error. 1205 * Returns 0 for success or NULL context or < 0 on error.
1158 */ 1206 */
1159int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode, struct kern_ipc_perm *ipcp) 1207int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode, struct kern_ipc_perm *ipcp)
1160{ 1208{
1161 struct audit_aux_data_ipcctl *ax; 1209 struct audit_aux_data_ipcctl *ax;
1162 struct audit_context *context = current->audit_context; 1210 struct audit_context *context = current->audit_context;
@@ -1174,7 +1222,7 @@ int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode, str
1174 ax->mode = mode; 1222 ax->mode = mode;
1175 selinux_get_ipc_sid(ipcp, &ax->osid); 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 ax->d.next = context->aux; 1226 ax->d.next = context->aux;
1179 context->aux = (void *)ax; 1227 context->aux = (void *)ax;
1180 return 0; 1228 return 0;