On Friday 31 March 2006 16:13, Dustin Kirkland wrote:
I know we discussed on IRC, but for everyone's benefit, we're
going to
call this record type AUDIT_IPC_SET_PERM and the function
audit_ipc_set_perm(), as it's called in each of the IPC_SET operations
on the ipc objects.
Hi,
I've reworked your rework patch so that it applies to the end of the current
stack of patches. Its included below. Please review for any serious omissions
or gaffs.
-Steve
diff -urp linux-2.6.16.x86_64.orig/include/linux/audit.h
linux-2.6.16.x86_64/include/linux/audit.h
--- linux-2.6.16.x86_64.orig/include/linux/audit.h 2006-04-02 15:48:21.000000000 -0400
+++ linux-2.6.16.x86_64/include/linux/audit.h 2006-04-02 15:48:55.000000000 -0400
@@ -83,6 +83,7 @@
#define AUDIT_CONFIG_CHANGE 1305 /* Audit system configuration change */
#define AUDIT_SOCKADDR 1306 /* sockaddr copied as syscall arg */
#define AUDIT_CWD 1307 /* Current working directory */
+#define AUDIT_IPC_SET_PERM 1311 /* IPC new permissions record type */
#define AUDIT_AVC 1400 /* SE Linux avc denial or grant */
#define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */
@@ -320,7 +321,8 @@ extern void auditsc_get_stamp(struct aud
struct timespec *t, unsigned int *serial);
extern int audit_set_loginuid(struct task_struct *task, uid_t loginuid);
extern uid_t audit_get_loginuid(struct audit_context *ctx);
-extern int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode,
struct kern_ipc_perm *ipcp);
+extern int audit_ipc_obj(struct kern_ipc_perm *ipcp);
+extern int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode,
struct kern_ipc_perm *ipcp);
extern int audit_socketcall(int nargs, unsigned long *args);
extern int audit_sockaddr(int len, void *addr);
extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt);
@@ -339,7 +341,8 @@ extern int audit_set_macxattr(const char
#define audit_inode_child(d,i,p) do { ; } while (0)
#define auditsc_get_stamp(c,t,s) do { BUG(); } while (0)
#define audit_get_loginuid(c) ({ -1; })
-#define audit_ipc_perms(q,u,g,m,i) ({ 0; })
+#define audit_ipc_obj(i) ({ 0; })
+#define audit_ipc_set_perm(q,u,g,m,i) ({ 0; })
#define audit_socketcall(n,a) ({ 0; })
#define audit_sockaddr(len, addr) ({ 0; })
#define audit_avc_path(dentry, mnt) ({ 0; })
diff -urp linux-2.6.16.x86_64.orig/ipc/msg.c linux-2.6.16.x86_64/ipc/msg.c
--- linux-2.6.16.x86_64.orig/ipc/msg.c 2006-04-02 15:48:28.000000000 -0400
+++ linux-2.6.16.x86_64/ipc/msg.c 2006-04-02 15:48:55.000000000 -0400
@@ -13,6 +13,9 @@
* mostly rewritten, threaded and wake-one semantics added
* MSGMAX limit removed, sysctl's added
* (c) 1999 Manfred Spraul <manfred(a)colorfullife.com>
+ *
+ * support for audit of ipc object properties and permission changes
+ * Dustin Kirkland <dustin.kirkland(a)us.ibm.com>
*/
#include <linux/capability.h>
@@ -446,6 +449,11 @@ asmlinkage long sys_msgctl (int msqid, i
if (msg_checkid(msq,msqid))
goto out_unlock_up;
ipcp = &msq->q_perm;
+
+ err = audit_ipc_obj(ipcp);
+ if (err)
+ goto out_unlock_up;
+
err = -EPERM;
if (current->euid != ipcp->cuid &&
current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN))
@@ -459,7 +467,8 @@ asmlinkage long sys_msgctl (int msqid, i
switch (cmd) {
case IPC_SET:
{
- if ((err = audit_ipc_perms(setbuf.qbytes, setbuf.uid, setbuf.gid, setbuf.mode, ipcp)))
+ err = audit_ipc_set_perm(setbuf.qbytes, setbuf.uid, setbuf.gid, setbuf.mode, ipcp);
+ if (err)
goto out_unlock_up;
err = -EPERM;
diff -urp linux-2.6.16.x86_64.orig/ipc/sem.c linux-2.6.16.x86_64/ipc/sem.c
--- linux-2.6.16.x86_64.orig/ipc/sem.c 2006-04-02 15:48:28.000000000 -0400
+++ linux-2.6.16.x86_64/ipc/sem.c 2006-04-02 15:48:55.000000000 -0400
@@ -61,6 +61,9 @@
* (c) 2001 Red Hat Inc <alan(a)redhat.com>
* Lockless wakeup
* (c) 2003 Manfred Spraul <manfred(a)colorfullife.com>
+ *
+ * support for audit of ipc object properties and permission changes
+ * Dustin Kirkland <dustin.kirkland(a)us.ibm.com>
*/
#include <linux/config.h>
@@ -819,6 +822,11 @@ static int semctl_down(int semid, int se
goto out_unlock;
}
ipcp = &sma->sem_perm;
+
+ err = audit_ipc_obj(ipcp);
+ if (err)
+ goto out_unlock;
+
if (current->euid != ipcp->cuid &&
current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN)) {
err=-EPERM;
@@ -835,7 +843,8 @@ static int semctl_down(int semid, int se
err = 0;
break;
case IPC_SET:
- if ((err = audit_ipc_perms(0, setbuf.uid, setbuf.gid, setbuf.mode, ipcp)))
+ err = audit_ipc_set_perm(0, setbuf.uid, setbuf.gid, setbuf.mode, ipcp);
+ if (err)
goto out_unlock;
ipcp->uid = setbuf.uid;
ipcp->gid = setbuf.gid;
diff -urp linux-2.6.16.x86_64.orig/ipc/shm.c linux-2.6.16.x86_64/ipc/shm.c
--- linux-2.6.16.x86_64.orig/ipc/shm.c 2006-04-02 15:48:28.000000000 -0400
+++ linux-2.6.16.x86_64/ipc/shm.c 2006-04-02 15:48:55.000000000 -0400
@@ -13,6 +13,8 @@
* Shared /dev/zero support, Kanoj Sarcar <kanoj(a)sgi.com>
* Move the mm functionality over to mm/shmem.c, Christoph Rohland <cr(a)sap.com>
*
+ * support for audit of ipc object properties and permission changes
+ * Dustin Kirkland <dustin.kirkland(a)us.ibm.com>
*/
#include <linux/config.h>
@@ -540,6 +542,10 @@ asmlinkage long sys_shmctl (int shmid, i
if(err)
goto out_unlock;
+ err = audit_ipc_obj(&(shp->shm_perm));
+ if (err)
+ goto out_unlock;
+
if (!capable(CAP_IPC_LOCK)) {
err = -EPERM;
if (current->euid != shp->shm_perm.uid &&
@@ -592,6 +598,10 @@ asmlinkage long sys_shmctl (int shmid, i
if(err)
goto out_unlock_up;
+ err = audit_ipc_obj(&(shp->shm_perm));
+ if (err)
+ goto out_unlock_up;
+
if (current->euid != shp->shm_perm.uid &&
current->euid != shp->shm_perm.cuid &&
!capable(CAP_SYS_ADMIN)) {
@@ -625,11 +635,15 @@ asmlinkage long sys_shmctl (int shmid, i
err=-EINVAL;
if(shp==NULL)
goto out_up;
- if ((err = audit_ipc_perms(0, setbuf.uid, setbuf.gid, setbuf.mode,
&(shp->shm_perm))))
- goto out_unlock_up;
err = shm_checkid(shp,shmid);
if(err)
goto out_unlock_up;
+ err = audit_ipc_obj(&(shp->shm_perm));
+ if (err)
+ goto out_unlock_up;
+ err = audit_ipc_set_perm(0, setbuf.uid, setbuf.gid, setbuf.mode,
&(shp->shm_perm));
+ if (err)
+ goto out_unlock_up;
err=-EPERM;
if (current->euid != shp->shm_perm.uid &&
current->euid != shp->shm_perm.cuid &&
diff -urp linux-2.6.16.x86_64.orig/ipc/util.c linux-2.6.16.x86_64/ipc/util.c
--- linux-2.6.16.x86_64.orig/ipc/util.c 2006-04-02 15:48:28.000000000 -0400
+++ linux-2.6.16.x86_64/ipc/util.c 2006-04-02 15:49:18.000000000 -0400
@@ -10,6 +10,8 @@
* Manfred Spraul <manfred(a)colorfullife.com>
* Oct 2002 - One lock per IPC id. RCU ipc_free for lock-free grow_ary().
* Mingming Cao <cmm(a)us.ibm.com>
+ * Mar 2006 - support for audit of ipc object properties
+ * Dustin Kirkland <dustin.kirkland(a)us.ibm.com>
*/
#include <linux/config.h>
@@ -27,6 +29,7 @@
#include <linux/workqueue.h>
#include <linux/seq_file.h>
#include <linux/proc_fs.h>
+#include <linux/audit.h>
#include <asm/unistd.h>
@@ -466,8 +469,10 @@ void ipc_rcu_putref(void *ptr)
int ipcperms (struct kern_ipc_perm *ipcp, short flag)
{ /* flag will most probably be 0 or S_...UGO from <linux/stat.h> */
- int requested_mode, granted_mode;
+ int requested_mode, granted_mode, err;
+ if (unlikely((err = audit_ipc_obj(ipcp))))
+ return err;
requested_mode = (flag >> 6) | (flag >> 3) | flag;
granted_mode = ipcp->mode;
if (current->euid == ipcp->cuid || current->euid == ipcp->uid)
diff -urp linux-2.6.16.x86_64.orig/kernel/auditsc.c linux-2.6.16.x86_64/kernel/auditsc.c
--- linux-2.6.16.x86_64.orig/kernel/auditsc.c 2006-04-02 15:48:28.000000000 -0400
+++ linux-2.6.16.x86_64/kernel/auditsc.c 2006-04-02 15:48:55.000000000 -0400
@@ -670,6 +670,25 @@ static void audit_log_exit(struct audit_
}
break; }
+ case AUDIT_IPC_SET_PERM: {
+ struct audit_aux_data_ipcctl *axi = (void *)aux;
+ audit_log_format(ab,
+ " new qbytes=%lx new iuid=%u new igid=%u new mode=%x",
+ axi->qbytes, axi->uid, axi->gid, axi->mode);
+ if (axi->osid != 0) {
+ char *ctx = NULL;
+ u32 len;
+ if (selinux_ctxid_to_string(
+ axi->osid, &ctx, &len)) {
+ audit_log_format(ab, " osid=%u",
+ axi->osid);
+ call_panic = 1;
+ } else
+ audit_log_format(ab, " obj=%s", ctx);
+ kfree(ctx);
+ }
+ break; }
+
case AUDIT_SOCKETCALL: {
int i;
struct audit_aux_data_socketcall *axs = (void *)aux;
@@ -1155,7 +1174,36 @@ uid_t audit_get_loginuid(struct audit_co
}
/**
- * audit_ipc_perms - record audit data for ipc
+ * audit_ipc_obj - record audit data for ipc object
+ * @ipcp: ipc permissions
+ *
+ * Returns 0 for success or NULL context or < 0 on error.
+ */
+int audit_ipc_obj(struct kern_ipc_perm *ipcp)
+{
+ struct audit_aux_data_ipcctl *ax;
+ struct audit_context *context = current->audit_context;
+
+ if (likely(!context))
+ return 0;
+
+ ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
+ if (!ax)
+ return -ENOMEM;
+
+ ax->uid = ipcp->uid;
+ ax->gid = ipcp->gid;
+ ax->mode = ipcp->mode;
+ selinux_get_ipc_sid(ipcp, &ax->osid);
+
+ ax->d.type = AUDIT_IPC;
+ ax->d.next = context->aux;
+ context->aux = (void *)ax;
+ return 0;
+}
+
+/**
+ * audit_ipc_set_perm - record audit data for new ipc permissions
* @qbytes: msgq bytes
* @uid: msgq user id
* @gid: msgq group id
@@ -1163,7 +1211,7 @@ uid_t audit_get_loginuid(struct audit_co
*
* Returns 0 for success or NULL context or < 0 on error.
*/
-int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode, struct
kern_ipc_perm *ipcp)
+int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode, struct
kern_ipc_perm *ipcp)
{
struct audit_aux_data_ipcctl *ax;
struct audit_context *context = current->audit_context;
@@ -1181,7 +1229,7 @@ int audit_ipc_perms(unsigned long qbytes
ax->mode = mode;
selinux_get_ipc_sid(ipcp, &ax->osid);
- ax->d.type = AUDIT_IPC;
+ ax->d.type = AUDIT_IPC_SET_PERM;
ax->d.next = context->aux;
context->aux = (void *)ax;
return 0;