>From 694502e960af954c4203d1b76837e51ce6720576 Mon Sep 17 00:00:00 2001 From: Stephen Smalley Date: Wed, 6 Feb 2013 11:15:08 -0500 Subject: [PATCH] Fix selinux_msg_queue_msgrcv() oops. Fix an oops in selinux_msg_queue_msgrcv() by ensuring that copied messages preserve security information. Signed-off-by: Stephen Smalley Reported-by: Tommi Rantala --- 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