int     lbs_cred;
        int     lbs_file;
        int     lbs_inode;
+       int     lbs_ipc;
+       int     lbs_msg_msg;
        int     lbs_task;
 };
 
 
 #include <linux/personality.h>
 #include <linux/backing-dev.h>
 #include <linux/string.h>
+#include <linux/msg.h>
 #include <net/flow.h>
 
 #define MAX_LSM_EVM_XATTR      2
        if (needed->lbs_inode && blob_sizes.lbs_inode == 0)
                blob_sizes.lbs_inode = sizeof(struct rcu_head);
        lsm_set_blob_size(&needed->lbs_inode, &blob_sizes.lbs_inode);
+       lsm_set_blob_size(&needed->lbs_ipc, &blob_sizes.lbs_ipc);
+       lsm_set_blob_size(&needed->lbs_msg_msg, &blob_sizes.lbs_msg_msg);
        lsm_set_blob_size(&needed->lbs_task, &blob_sizes.lbs_task);
 }
 
        init_debug("cred blob size     = %d\n", blob_sizes.lbs_cred);
        init_debug("file blob size     = %d\n", blob_sizes.lbs_file);
        init_debug("inode blob size    = %d\n", blob_sizes.lbs_inode);
+       init_debug("ipc blob size      = %d\n", blob_sizes.lbs_ipc);
+       init_debug("msg_msg blob size  = %d\n", blob_sizes.lbs_msg_msg);
        init_debug("task blob size     = %d\n", blob_sizes.lbs_task);
 
        /*
        return 0;
 }
 
+/**
+ * lsm_ipc_alloc - allocate a composite ipc blob
+ * @kip: the ipc that needs a blob
+ *
+ * Allocate the ipc blob for all the modules
+ *
+ * Returns 0, or -ENOMEM if memory can't be allocated.
+ */
+int lsm_ipc_alloc(struct kern_ipc_perm *kip)
+{
+       if (blob_sizes.lbs_ipc == 0) {
+               kip->security = NULL;
+               return 0;
+       }
+
+       kip->security = kzalloc(blob_sizes.lbs_ipc, GFP_KERNEL);
+       if (kip->security == NULL)
+               return -ENOMEM;
+       return 0;
+}
+
+/**
+ * lsm_msg_msg_alloc - allocate a composite msg_msg blob
+ * @mp: the msg_msg that needs a blob
+ *
+ * Allocate the ipc blob for all the modules
+ *
+ * Returns 0, or -ENOMEM if memory can't be allocated.
+ */
+int lsm_msg_msg_alloc(struct msg_msg *mp)
+{
+       if (blob_sizes.lbs_msg_msg == 0) {
+               mp->security = NULL;
+               return 0;
+       }
+
+       mp->security = kzalloc(blob_sizes.lbs_msg_msg, GFP_KERNEL);
+       if (mp->security == NULL)
+               return -ENOMEM;
+       return 0;
+}
+
 /**
  * lsm_early_task - during initialization allocate a composite task blob
  * @task: the task that needs a blob
 
 int security_msg_msg_alloc(struct msg_msg *msg)
 {
-       return call_int_hook(msg_msg_alloc_security, 0, msg);
+       int rc = lsm_msg_msg_alloc(msg);
+
+       if (unlikely(rc))
+               return rc;
+       rc = call_int_hook(msg_msg_alloc_security, 0, msg);
+       if (unlikely(rc))
+               security_msg_msg_free(msg);
+       return rc;
 }
 
 void security_msg_msg_free(struct msg_msg *msg)
 {
        call_void_hook(msg_msg_free_security, msg);
+       kfree(msg->security);
+       msg->security = NULL;
 }
 
 int security_msg_queue_alloc(struct kern_ipc_perm *msq)
 {
-       return call_int_hook(msg_queue_alloc_security, 0, msq);
+       int rc = lsm_ipc_alloc(msq);
+
+       if (unlikely(rc))
+               return rc;
+       rc = call_int_hook(msg_queue_alloc_security, 0, msq);
+       if (unlikely(rc))
+               security_msg_queue_free(msq);
+       return rc;
 }
 
 void security_msg_queue_free(struct kern_ipc_perm *msq)
 {
        call_void_hook(msg_queue_free_security, msq);
+       kfree(msq->security);
+       msq->security = NULL;
 }
 
 int security_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg)
 
 int security_shm_alloc(struct kern_ipc_perm *shp)
 {
-       return call_int_hook(shm_alloc_security, 0, shp);
+       int rc = lsm_ipc_alloc(shp);
+
+       if (unlikely(rc))
+               return rc;
+       rc = call_int_hook(shm_alloc_security, 0, shp);
+       if (unlikely(rc))
+               security_shm_free(shp);
+       return rc;
 }
 
 void security_shm_free(struct kern_ipc_perm *shp)
 {
        call_void_hook(shm_free_security, shp);
+       kfree(shp->security);
+       shp->security = NULL;
 }
 
 int security_shm_associate(struct kern_ipc_perm *shp, int shmflg)
 
 int security_sem_alloc(struct kern_ipc_perm *sma)
 {
-       return call_int_hook(sem_alloc_security, 0, sma);
+       int rc = lsm_ipc_alloc(sma);
+
+       if (unlikely(rc))
+               return rc;
+       rc = call_int_hook(sem_alloc_security, 0, sma);
+       if (unlikely(rc))
+               security_sem_free(sma);
+       return rc;
 }
 
 void security_sem_free(struct kern_ipc_perm *sma)
 {
        call_void_hook(sem_free_security, sma);
+       kfree(sma->security);
+       sma->security = NULL;
 }
 
 int security_sem_associate(struct kern_ipc_perm *sma, int semflg)
 
        return selinux_nlmsg_perm(sk, skb);
 }
 
-static int ipc_alloc_security(struct kern_ipc_perm *perm,
-                             u16 sclass)
+static void ipc_init_security(struct ipc_security_struct *isec, u16 sclass)
 {
-       struct ipc_security_struct *isec;
-
-       isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
-       if (!isec)
-               return -ENOMEM;
-
        isec->sclass = sclass;
        isec->sid = current_sid();
-       perm->security = isec;
-
-       return 0;
-}
-
-static void ipc_free_security(struct kern_ipc_perm *perm)
-{
-       struct ipc_security_struct *isec = perm->security;
-       perm->security = NULL;
-       kfree(isec);
 }
 
 static int msg_msg_alloc_security(struct msg_msg *msg)
 {
        struct msg_security_struct *msec;
 
-       msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
-       if (!msec)
-               return -ENOMEM;
-
+       msec = selinux_msg_msg(msg);
        msec->sid = SECINITSID_UNLABELED;
-       msg->security = msec;
 
        return 0;
 }
 
-static void msg_msg_free_security(struct msg_msg *msg)
-{
-       struct msg_security_struct *msec = msg->security;
-
-       msg->security = NULL;
-       kfree(msec);
-}
-
 static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
                        u32 perms)
 {
        return msg_msg_alloc_security(msg);
 }
 
-static void selinux_msg_msg_free_security(struct msg_msg *msg)
-{
-       msg_msg_free_security(msg);
-}
-
 /* message queue security operations */
 static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq)
 {
        u32 sid = current_sid();
        int rc;
 
-       rc = ipc_alloc_security(msq, SECCLASS_MSGQ);
-       if (rc)
-               return rc;
-
-       isec = msq->security;
+       isec = selinux_ipc(msq);
+       ipc_init_security(isec, SECCLASS_MSGQ);
 
        ad.type = LSM_AUDIT_DATA_IPC;
        ad.u.ipc_id = msq->key;
        rc = avc_has_perm(&selinux_state,
                          sid, isec->sid, SECCLASS_MSGQ,
                          MSGQ__CREATE, &ad);
-       if (rc) {
-               ipc_free_security(msq);
-               return rc;
-       }
-       return 0;
-}
-
-static void selinux_msg_queue_free_security(struct kern_ipc_perm *msq)
-{
-       ipc_free_security(msq);
+       return rc;
 }
 
 static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg)
        u32 sid = current_sid();
        int rc;
 
-       rc = ipc_alloc_security(shp, SECCLASS_SHM);
-       if (rc)
-               return rc;
-
-       isec = shp->security;
+       isec = selinux_ipc(shp);
+       ipc_init_security(isec, SECCLASS_SHM);
 
        ad.type = LSM_AUDIT_DATA_IPC;
        ad.u.ipc_id = shp->key;
        rc = avc_has_perm(&selinux_state,
                          sid, isec->sid, SECCLASS_SHM,
                          SHM__CREATE, &ad);
-       if (rc) {
-               ipc_free_security(shp);
-               return rc;
-       }
-       return 0;
-}
-
-static void selinux_shm_free_security(struct kern_ipc_perm *shp)
-{
-       ipc_free_security(shp);
+       return rc;
 }
 
 static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg)
        u32 sid = current_sid();
        int rc;
 
-       rc = ipc_alloc_security(sma, SECCLASS_SEM);
-       if (rc)
-               return rc;
-
-       isec = sma->security;
+       isec = selinux_ipc(sma);
+       ipc_init_security(isec, SECCLASS_SEM);
 
        ad.type = LSM_AUDIT_DATA_IPC;
        ad.u.ipc_id = sma->key;
        rc = avc_has_perm(&selinux_state,
                          sid, isec->sid, SECCLASS_SEM,
                          SEM__CREATE, &ad);
-       if (rc) {
-               ipc_free_security(sma);
-               return rc;
-       }
-       return 0;
-}
-
-static void selinux_sem_free_security(struct kern_ipc_perm *sma)
-{
-       ipc_free_security(sma);
+       return rc;
 }
 
 static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg)
        .lbs_cred = sizeof(struct task_security_struct),
        .lbs_file = sizeof(struct file_security_struct),
        .lbs_inode = sizeof(struct inode_security_struct),
+       .lbs_ipc = sizeof(struct ipc_security_struct),
+       .lbs_msg_msg = sizeof(struct msg_security_struct),
 };
 
 static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
        LSM_HOOK_INIT(ipc_getsecid, selinux_ipc_getsecid),
 
        LSM_HOOK_INIT(msg_msg_alloc_security, selinux_msg_msg_alloc_security),
-       LSM_HOOK_INIT(msg_msg_free_security, selinux_msg_msg_free_security),
 
        LSM_HOOK_INIT(msg_queue_alloc_security,
                        selinux_msg_queue_alloc_security),
-       LSM_HOOK_INIT(msg_queue_free_security, selinux_msg_queue_free_security),
        LSM_HOOK_INIT(msg_queue_associate, selinux_msg_queue_associate),
        LSM_HOOK_INIT(msg_queue_msgctl, selinux_msg_queue_msgctl),
        LSM_HOOK_INIT(msg_queue_msgsnd, selinux_msg_queue_msgsnd),
        LSM_HOOK_INIT(msg_queue_msgrcv, selinux_msg_queue_msgrcv),
 
        LSM_HOOK_INIT(shm_alloc_security, selinux_shm_alloc_security),
-       LSM_HOOK_INIT(shm_free_security, selinux_shm_free_security),
        LSM_HOOK_INIT(shm_associate, selinux_shm_associate),
        LSM_HOOK_INIT(shm_shmctl, selinux_shm_shmctl),
        LSM_HOOK_INIT(shm_shmat, selinux_shm_shmat),
 
        LSM_HOOK_INIT(sem_alloc_security, selinux_sem_alloc_security),
-       LSM_HOOK_INIT(sem_free_security, selinux_sem_free_security),
        LSM_HOOK_INIT(sem_associate, selinux_sem_associate),
        LSM_HOOK_INIT(sem_semctl, selinux_sem_semctl),
        LSM_HOOK_INIT(sem_semop, selinux_sem_semop),
 
 static inline struct msg_security_struct *selinux_msg_msg(
                                                const struct msg_msg *msg_msg)
 {
-       return msg_msg->security;
+       return msg_msg->security + selinux_blob_sizes.lbs_msg_msg;
 }
 
 static inline struct ipc_security_struct *selinux_ipc(
                                                const struct kern_ipc_perm *ipc)
 {
-       return ipc->security;
+       return ipc->security + selinux_blob_sizes.lbs_ipc;
 }
 
 #endif /* _SELINUX_OBJSEC_H_ */
 
 
 static inline struct smack_known **smack_msg_msg(const struct msg_msg *msg)
 {
-       return (struct smack_known **)&msg->security;
+       return msg->security + smack_blob_sizes.lbs_msg_msg;
 }
 
 static inline struct smack_known **smack_ipc(const struct kern_ipc_perm *ipc)
 {
-       return (struct smack_known **)&ipc->security;
+       return ipc->security + smack_blob_sizes.lbs_ipc;
 }
 
 /*
 
  */
 static int smack_msg_msg_alloc_security(struct msg_msg *msg)
 {
-       struct smack_known *skp = smk_of_current();
+       struct smack_known **blob = smack_msg_msg(msg);
 
-       msg->security = skp;
+       *blob = smk_of_current();
        return 0;
 }
 
-/**
- * smack_msg_msg_free_security - Clear the security blob for msg_msg
- * @msg: the object
- *
- * Clears the blob pointer
- */
-static void smack_msg_msg_free_security(struct msg_msg *msg)
-{
-       msg->security = NULL;
-}
-
 /**
  * smack_of_ipc - the smack pointer for the ipc
  * @isp: the object
        return 0;
 }
 
-/**
- * smack_ipc_free_security - Clear the security blob for ipc
- * @isp: the object
- *
- * Clears the blob pointer
- */
-static void smack_ipc_free_security(struct kern_ipc_perm *isp)
-{
-       isp->security = NULL;
-}
-
 /**
  * smk_curacc_shm : check if current has access on shm
  * @isp : the object
        .lbs_cred = sizeof(struct task_smack),
        .lbs_file = sizeof(struct smack_known *),
        .lbs_inode = sizeof(struct inode_smack),
+       .lbs_ipc = sizeof(struct smack_known *),
+       .lbs_msg_msg = sizeof(struct smack_known *),
 };
 
 static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
        LSM_HOOK_INIT(ipc_getsecid, smack_ipc_getsecid),
 
        LSM_HOOK_INIT(msg_msg_alloc_security, smack_msg_msg_alloc_security),
-       LSM_HOOK_INIT(msg_msg_free_security, smack_msg_msg_free_security),
 
        LSM_HOOK_INIT(msg_queue_alloc_security, smack_ipc_alloc_security),
-       LSM_HOOK_INIT(msg_queue_free_security, smack_ipc_free_security),
        LSM_HOOK_INIT(msg_queue_associate, smack_msg_queue_associate),
        LSM_HOOK_INIT(msg_queue_msgctl, smack_msg_queue_msgctl),
        LSM_HOOK_INIT(msg_queue_msgsnd, smack_msg_queue_msgsnd),
        LSM_HOOK_INIT(msg_queue_msgrcv, smack_msg_queue_msgrcv),
 
        LSM_HOOK_INIT(shm_alloc_security, smack_ipc_alloc_security),
-       LSM_HOOK_INIT(shm_free_security, smack_ipc_free_security),
        LSM_HOOK_INIT(shm_associate, smack_shm_associate),
        LSM_HOOK_INIT(shm_shmctl, smack_shm_shmctl),
        LSM_HOOK_INIT(shm_shmat, smack_shm_shmat),
 
        LSM_HOOK_INIT(sem_alloc_security, smack_ipc_alloc_security),
-       LSM_HOOK_INIT(sem_free_security, smack_ipc_free_security),
        LSM_HOOK_INIT(sem_associate, smack_sem_associate),
        LSM_HOOK_INIT(sem_semctl, smack_sem_semctl),
        LSM_HOOK_INIT(sem_semop, smack_sem_semop),