[PATCH] Fix selinux_msg_queue_msgrcv() oops.

From: Stephen Smalley
Date: Wed Feb 06 2013 - 11:15:08 EST


Fix an oops in selinux_msg_queue_msgrcv() by ensuring that
copied messages preserve security information.

Signed-off-by: Stephen Smalley <sds@xxxxxxxxxxxxx>
Reported-by: Tommi Rantala <tt.rantala@xxxxxxxxx>
---
include/linux/security.h | 12 ++++++++++++
ipc/msgutil.c | 6 +++++-
security/security.c | 5 +++++
security/selinux/hooks.c | 10 ++++++++++
4 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/include/linux/security.h b/include/linux/security.h
index eee7478..4737635 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1126,6 +1126,11 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
* created.
* @msg contains the message structure to be modified.
* Return 0 if operation was successful and permission is granted.
+ * @msg_msg_copy_security:
+ * Propagate security information on a msg copy operation.
+ * @src contains the source message structure.
+ * @dst contains the destination message structure.
+ * Return 0 if operation was successful.
* @msg_msg_free_security:
* Deallocate the security structure for this message.
* @msg contains the message structure to be modified.
@@ -1553,6 +1558,7 @@ struct security_operations {
void (*ipc_getsecid) (struct kern_ipc_perm *ipcp, u32 *secid);

int (*msg_msg_alloc_security) (struct msg_msg *msg);
+ int (*msg_msg_copy_security) (struct msg_msg *src, struct msg_msg *dst);
void (*msg_msg_free_security) (struct msg_msg *msg);

int (*msg_queue_alloc_security) (struct msg_queue *msq);
@@ -1811,6 +1817,7 @@ void security_task_to_inode(struct task_struct *p, struct inode *inode);
int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag);
void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid);
int security_msg_msg_alloc(struct msg_msg *msg);
+int security_msg_msg_copy(struct msg_msg *src, struct msg_msg *dst);
void security_msg_msg_free(struct msg_msg *msg);
int security_msg_queue_alloc(struct msg_queue *msq);
void security_msg_queue_free(struct msg_queue *msq);
@@ -2409,6 +2416,11 @@ static inline int security_msg_msg_alloc(struct msg_msg *msg)
return 0;
}

+static inline int security_msg_msg_copy(struct msg_msg *src, struct msg_msg *dst)
+{
+ return 0;
+}
+
static inline void security_msg_msg_free(struct msg_msg *msg)
{ }

diff --git a/ipc/msgutil.c b/ipc/msgutil.c
index ebfcbfa..7837257 100644
--- a/ipc/msgutil.c
+++ b/ipc/msgutil.c
@@ -108,6 +108,7 @@ struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst)
struct msg_msgseg *dst_pseg, *src_pseg;
int len = src->m_ts;
int alen;
+ int err;

BUG_ON(dst == NULL);
if (src->m_ts > dst->m_ts)
@@ -118,7 +119,10 @@ struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst)
alen = DATALEN_MSG;

dst->next = NULL;
- dst->security = NULL;
+
+ err = security_msg_msg_copy(src, dst);
+ if (err < 0)
+ return ERR_PTR(err);

memcpy(dst + 1, src + 1, alen);

diff --git a/security/security.c b/security/security.c
index 7b88c6a..85cd39d 100644
--- a/security/security.c
+++ b/security/security.c
@@ -936,6 +936,11 @@ int security_msg_msg_alloc(struct msg_msg *msg)
return security_ops->msg_msg_alloc_security(msg);
}

+int security_msg_msg_copy(struct msg_msg *src, struct msg_msg *dst)
+{
+ return security_ops->msg_msg_copy_security(src, dst);
+}
+
void security_msg_msg_free(struct msg_msg *msg)
{
security_ops->msg_msg_free_security(msg);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index ef26e96..79f93ad 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4840,6 +4840,15 @@ static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
return msg_msg_alloc_security(msg);
}

+static int selinux_msg_msg_copy_security(struct msg_msg *src, struct msg_msg *dst)
+{
+ struct msg_security_struct *smsec, *dmsec;
+ smsec = src->security;
+ dmsec = dst->security;
+ dmsec->sid = smsec->sid;
+ return 0;
+}
+
static void selinux_msg_msg_free_security(struct msg_msg *msg)
{
msg_msg_free_security(msg);
@@ -5603,6 +5612,7 @@ static struct security_operations selinux_ops = {
.ipc_getsecid = selinux_ipc_getsecid,

.msg_msg_alloc_security = selinux_msg_msg_alloc_security,
+ .msg_msg_copy_security = selinux_msg_msg_copy_security,
.msg_msg_free_security = selinux_msg_msg_free_security,

.msg_queue_alloc_security = selinux_msg_queue_alloc_security,
--
1.7.11.7


--------------050308000306020901090205--
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/