#define AUDIT_CWD              1307    /* Current working directory */
 #define AUDIT_EXECVE           1309    /* execve arguments */
 #define AUDIT_IPC_SET_PERM     1311    /* IPC new permissions record type */
+#define AUDIT_MQ_OPEN          1312    /* POSIX MQ open record type */
+#define AUDIT_MQ_SENDRECV      1313    /* POSIX MQ send/receive record type */
+#define AUDIT_MQ_NOTIFY                1314    /* POSIX MQ notify record type */
+#define AUDIT_MQ_GETSETATTR    1315    /* POSIX MQ get/set attribute record type */
 
 #define AUDIT_AVC              1400    /* SE Linux avc denial or grant */
 #define AUDIT_SELINUX_ERR      1401    /* Internal SE Linux Errors */
 struct inode;
 struct netlink_skb_parms;
 struct linux_binprm;
+struct mq_attr;
+struct mqstat;
 
 #define AUDITSC_INVALID 0
 #define AUDITSC_SUCCESS 1
 extern int audit_sockaddr(int len, void *addr);
 extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt);
 extern int audit_set_macxattr(const char *name);
+extern int __audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr);
+extern int __audit_mq_timedsend(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec __user *u_abs_timeout);
+extern int __audit_mq_timedreceive(mqd_t mqdes, size_t msg_len, unsigned int __user *u_msg_prio, const struct timespec __user *u_abs_timeout);
+extern int __audit_mq_notify(mqd_t mqdes, const struct sigevent __user *u_notification);
+extern int __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat);
 
 static inline int audit_ipc_obj(struct kern_ipc_perm *ipcp)
 {
                return __audit_ipc_set_perm(qbytes, uid, gid, mode);
        return 0;
 }
+static inline int audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr)
+{
+       if (unlikely(current->audit_context))
+               return __audit_mq_open(oflag, mode, u_attr);
+       return 0;
+}
+static inline int audit_mq_timedsend(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec __user *u_abs_timeout)
+{
+       if (unlikely(current->audit_context))
+               return __audit_mq_timedsend(mqdes, msg_len, msg_prio, u_abs_timeout);
+       return 0;
+}
+static inline int audit_mq_timedreceive(mqd_t mqdes, size_t msg_len, unsigned int __user *u_msg_prio, const struct timespec __user *u_abs_timeout)
+{
+       if (unlikely(current->audit_context))
+               return __audit_mq_timedreceive(mqdes, msg_len, u_msg_prio, u_abs_timeout);
+       return 0;
+}
+static inline int audit_mq_notify(mqd_t mqdes, const struct sigevent __user *u_notification)
+{
+       if (unlikely(current->audit_context))
+               return __audit_mq_notify(mqdes, u_notification);
+       return 0;
+}
+static inline int audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
+{
+       if (unlikely(current->audit_context))
+               return __audit_mq_getsetattr(mqdes, mqstat);
+       return 0;
+}
 #else
 #define audit_alloc(t) ({ 0; })
 #define audit_free(t) do { ; } while (0)
 #define audit_sockaddr(len, addr) ({ 0; })
 #define audit_avc_path(dentry, mnt) ({ 0; })
 #define audit_set_macxattr(n) do { ; } while (0)
+#define audit_mq_open(o,m,a) ({ 0; })
+#define audit_mq_timedsend(d,l,p,t) ({ 0; })
+#define audit_mq_timedreceive(d,l,p,t) ({ 0; })
+#define audit_mq_notify(d,n) ({ 0; })
+#define audit_mq_getsetattr(d,s) ({ 0; })
 #endif
 
 #ifdef CONFIG_AUDIT
 
  *
  * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
  * Copyright 2005 Hewlett-Packard Development Company, L.P.
- * Copyright (C) 2005 IBM Corporation
+ * Copyright (C) 2005, 2006 IBM Corporation
  * All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * this file -- see entry.S) is based on a GPL'd patch written by
  * okir@suse.de and Copyright 2003 SuSE Linux AG.
  *
+ * POSIX message queue support added by George Wilson <ltcgcw@us.ibm.com>,
+ * 2006.
+ *
  * The support of additional filter rules compares (>, <, >=, <=) was
  * added by Dustin Kirkland <dustin.kirkland@us.ibm.com>, 2005.
  *
 #include <linux/module.h>
 #include <linux/mount.h>
 #include <linux/socket.h>
+#include <linux/mqueue.h>
 #include <linux/audit.h>
 #include <linux/personality.h>
 #include <linux/time.h>
 
 #define AUDIT_AUX_IPCPERM      0
 
+struct audit_aux_data_mq_open {
+       struct audit_aux_data   d;
+       int                     oflag;
+       mode_t                  mode;
+       struct mq_attr          attr;
+};
+
+struct audit_aux_data_mq_sendrecv {
+       struct audit_aux_data   d;
+       mqd_t                   mqdes;
+       size_t                  msg_len;
+       unsigned int            msg_prio;
+       struct timespec         abs_timeout;
+};
+
+struct audit_aux_data_mq_notify {
+       struct audit_aux_data   d;
+       mqd_t                   mqdes;
+       struct sigevent         notification;
+};
+
+struct audit_aux_data_mq_getsetattr {
+       struct audit_aux_data   d;
+       mqd_t                   mqdes;
+       struct mq_attr          mqstat;
+};
+
 struct audit_aux_data_ipcctl {
        struct audit_aux_data   d;
        struct ipc_perm         p;
                        continue; /* audit_panic has been called */
 
                switch (aux->type) {
+               case AUDIT_MQ_OPEN: {
+                       struct audit_aux_data_mq_open *axi = (void *)aux;
+                       audit_log_format(ab,
+                               "oflag=0x%x mode=%#o mq_flags=0x%lx mq_maxmsg=%ld "
+                               "mq_msgsize=%ld mq_curmsgs=%ld",
+                               axi->oflag, axi->mode, axi->attr.mq_flags,
+                               axi->attr.mq_maxmsg, axi->attr.mq_msgsize,
+                               axi->attr.mq_curmsgs);
+                       break; }
+
+               case AUDIT_MQ_SENDRECV: {
+                       struct audit_aux_data_mq_sendrecv *axi = (void *)aux;
+                       audit_log_format(ab,
+                               "mqdes=%d msg_len=%zd msg_prio=%u "
+                               "abs_timeout_sec=%ld abs_timeout_nsec=%ld",
+                               axi->mqdes, axi->msg_len, axi->msg_prio,
+                               axi->abs_timeout.tv_sec, axi->abs_timeout.tv_nsec);
+                       break; }
+
+               case AUDIT_MQ_NOTIFY: {
+                       struct audit_aux_data_mq_notify *axi = (void *)aux;
+                       audit_log_format(ab,
+                               "mqdes=%d sigev_signo=%d",
+                               axi->mqdes,
+                               axi->notification.sigev_signo);
+                       break; }
+
+               case AUDIT_MQ_GETSETATTR: {
+                       struct audit_aux_data_mq_getsetattr *axi = (void *)aux;
+                       audit_log_format(ab,
+                               "mqdes=%d mq_flags=0x%lx mq_maxmsg=%ld mq_msgsize=%ld "
+                               "mq_curmsgs=%ld ",
+                               axi->mqdes,
+                               axi->mqstat.mq_flags, axi->mqstat.mq_maxmsg,
+                               axi->mqstat.mq_msgsize, axi->mqstat.mq_curmsgs);
+                       break; }
+
                case AUDIT_IPC: {
                        struct audit_aux_data_ipcctl *axi = (void *)aux;
                        audit_log_format(ab, 
        return ctx ? ctx->loginuid : -1;
 }
 
+/**
+ * __audit_mq_open - record audit data for a POSIX MQ open
+ * @oflag: open flag
+ * @mode: mode bits
+ * @u_attr: queue attributes
+ *
+ * Returns 0 for success or NULL context or < 0 on error.
+ */
+int __audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr)
+{
+       struct audit_aux_data_mq_open *ax;
+       struct audit_context *context = current->audit_context;
+
+       if (!audit_enabled)
+               return 0;
+
+       if (likely(!context))
+               return 0;
+
+       ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
+       if (!ax)
+               return -ENOMEM;
+
+       if (u_attr != NULL) {
+               if (copy_from_user(&ax->attr, u_attr, sizeof(ax->attr))) {
+                       kfree(ax);
+                       return -EFAULT;
+               }
+       } else
+               memset(&ax->attr, 0, sizeof(ax->attr));
+
+       ax->oflag = oflag;
+       ax->mode = mode;
+
+       ax->d.type = AUDIT_MQ_OPEN;
+       ax->d.next = context->aux;
+       context->aux = (void *)ax;
+       return 0;
+}
+
+/**
+ * __audit_mq_timedsend - record audit data for a POSIX MQ timed send
+ * @mqdes: MQ descriptor
+ * @msg_len: Message length
+ * @msg_prio: Message priority
+ * @abs_timeout: Message timeout in absolute time
+ *
+ * Returns 0 for success or NULL context or < 0 on error.
+ */
+int __audit_mq_timedsend(mqd_t mqdes, size_t msg_len, unsigned int msg_prio,
+                       const struct timespec __user *u_abs_timeout)
+{
+       struct audit_aux_data_mq_sendrecv *ax;
+       struct audit_context *context = current->audit_context;
+
+       if (!audit_enabled)
+               return 0;
+
+       if (likely(!context))
+               return 0;
+
+       ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
+       if (!ax)
+               return -ENOMEM;
+
+       if (u_abs_timeout != NULL) {
+               if (copy_from_user(&ax->abs_timeout, u_abs_timeout, sizeof(ax->abs_timeout))) {
+                       kfree(ax);
+                       return -EFAULT;
+               }
+       } else
+               memset(&ax->abs_timeout, 0, sizeof(ax->abs_timeout));
+
+       ax->mqdes = mqdes;
+       ax->msg_len = msg_len;
+       ax->msg_prio = msg_prio;
+
+       ax->d.type = AUDIT_MQ_SENDRECV;
+       ax->d.next = context->aux;
+       context->aux = (void *)ax;
+       return 0;
+}
+
+/**
+ * __audit_mq_timedreceive - record audit data for a POSIX MQ timed receive
+ * @mqdes: MQ descriptor
+ * @msg_len: Message length
+ * @msg_prio: Message priority
+ * @abs_timeout: Message timeout in absolute time
+ *
+ * Returns 0 for success or NULL context or < 0 on error.
+ */
+int __audit_mq_timedreceive(mqd_t mqdes, size_t msg_len,
+                               unsigned int __user *u_msg_prio,
+                               const struct timespec __user *u_abs_timeout)
+{
+       struct audit_aux_data_mq_sendrecv *ax;
+       struct audit_context *context = current->audit_context;
+
+       if (!audit_enabled)
+               return 0;
+
+       if (likely(!context))
+               return 0;
+
+       ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
+       if (!ax)
+               return -ENOMEM;
+
+       if (u_msg_prio != NULL) {
+               if (get_user(ax->msg_prio, u_msg_prio)) {
+                       kfree(ax);
+                       return -EFAULT;
+               }
+       } else
+               ax->msg_prio = 0;
+
+       if (u_abs_timeout != NULL) {
+               if (copy_from_user(&ax->abs_timeout, u_abs_timeout, sizeof(ax->abs_timeout))) {
+                       kfree(ax);
+                       return -EFAULT;
+               }
+       } else
+               memset(&ax->abs_timeout, 0, sizeof(ax->abs_timeout));
+
+       ax->mqdes = mqdes;
+       ax->msg_len = msg_len;
+
+       ax->d.type = AUDIT_MQ_SENDRECV;
+       ax->d.next = context->aux;
+       context->aux = (void *)ax;
+       return 0;
+}
+
+/**
+ * __audit_mq_notify - record audit data for a POSIX MQ notify
+ * @mqdes: MQ descriptor
+ * @u_notification: Notification event
+ *
+ * Returns 0 for success or NULL context or < 0 on error.
+ */
+
+int __audit_mq_notify(mqd_t mqdes, const struct sigevent __user *u_notification)
+{
+       struct audit_aux_data_mq_notify *ax;
+       struct audit_context *context = current->audit_context;
+
+       if (!audit_enabled)
+               return 0;
+
+       if (likely(!context))
+               return 0;
+
+       ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
+       if (!ax)
+               return -ENOMEM;
+
+       if (u_notification != NULL) {
+               if (copy_from_user(&ax->notification, u_notification, sizeof(ax->notification))) {
+                       kfree(ax);
+                       return -EFAULT;
+               }
+       } else
+               memset(&ax->notification, 0, sizeof(ax->notification));
+
+       ax->mqdes = mqdes;
+
+       ax->d.type = AUDIT_MQ_NOTIFY;
+       ax->d.next = context->aux;
+       context->aux = (void *)ax;
+       return 0;
+}
+
+/**
+ * __audit_mq_getsetattr - record audit data for a POSIX MQ get/set attribute
+ * @mqdes: MQ descriptor
+ * @mqstat: MQ flags
+ *
+ * Returns 0 for success or NULL context or < 0 on error.
+ */
+int __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
+{
+       struct audit_aux_data_mq_getsetattr *ax;
+       struct audit_context *context = current->audit_context;
+
+       if (!audit_enabled)
+               return 0;
+
+       if (likely(!context))
+               return 0;
+
+       ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
+       if (!ax)
+               return -ENOMEM;
+
+       ax->mqdes = mqdes;
+       ax->mqstat = *mqstat;
+
+       ax->d.type = AUDIT_MQ_GETSETATTR;
+       ax->d.next = context->aux;
+       context->aux = (void *)ax;
+       return 0;
+}
+
 /**
  * audit_ipc_obj - record audit data for ipc object
  * @ipcp: ipc permissions