LSM: Infrastructure management of the ipc security blob
Move management of the kern_ipc_perm->security and
msg_msg->security blobs out of the individual security
modules and into the security infrastructure. Instead
of allocating the blobs from within the modules the modules
tell the infrastructure how much space is required, and
the space is allocated there.
Signed-off-by: Casey Schaufler
---
include/linux/lsm_hooks.h | 2 +
security/security.c | 91 +--
security/selinux/hooks.c | 116 ++
security/selinux/include/objsec.h | 13
security/smack/smack.h| 11 +++
security/smack/smack_lsm.c| 46
6 files changed, 148 insertions(+), 131 deletions(-)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 6057c603b979..f6dbde28833a 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -2031,6 +2031,8 @@ struct lsm_blob_sizes {
int lbs_cred;
int lbs_file;
int lbs_inode;
+ int lbs_ipc;
+ int lbs_msg_msg;
int lbs_task;
};
diff --git a/security/security.c b/security/security.c
index 7e11de7eec21..a151d728aed2 100644
--- a/security/security.c
+++ b/security/security.c
@@ -28,6 +28,7 @@
#include
#include
#include
+#include
#include
#include
@@ -117,6 +118,8 @@ int __init security_init(void)
pr_info("LSM: cred blob size = %d\n", blob_sizes.lbs_cred);
pr_info("LSM: file blob size = %d\n", blob_sizes.lbs_file);
pr_info("LSM: inode blob size = %d\n", blob_sizes.lbs_inode);
+ pr_info("LSM: ipc blob size= %d\n", blob_sizes.lbs_ipc);
+ pr_info("LSM: msg_msg blob size= %d\n", blob_sizes.lbs_msg_msg);
pr_info("LSM: task blob size = %d\n", blob_sizes.lbs_task);
#endif
@@ -302,6 +305,8 @@ void __init security_add_blobs(struct lsm_blob_sizes
*needed)
if (needed->lbs_inode && blob_sizes.lbs_inode == 0)
blob_sizes.lbs_inode = sizeof(struct rcu_head);
lsm_set_size(&needed->lbs_inode, &blob_sizes.lbs_inode);
+ lsm_set_size(&needed->lbs_ipc, &blob_sizes.lbs_ipc);
+ lsm_set_size(&needed->lbs_msg_msg, &blob_sizes.lbs_msg_msg);
lsm_set_size(&needed->lbs_task, &blob_sizes.lbs_task);
}
@@ -387,6 +392,48 @@ int lsm_task_alloc(struct task_struct *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
@@ -1468,22 +1515,40 @@ void security_ipc_getsecid(struct kern_ipc_perm *ipcp,
u32 *secid)
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)
@@ -1510,12 +1575,21 @@ int security_msg_queue_msgrcv(struct kern_ipc_perm
*msq, struct msg_msg *msg,