Currently, we check msg security only under RCU. Since selinux can free the security structure, through selinux_sem_free_security(), we can run into a use-after-free condition. This bug only affects msgctl syscalls, as msgsnd and msgrcv have already been updated. The fix is obvious, make sure we hold the kern_ipc_perm.lock while performing these security checks. Reported-by: Manfred Spraul <manfred@xxxxxxxxxxxxxxxx> Cc: stable@xxxxxxxxxxxxxxx # for 3.11 Signed-off-by: Davidlohr Bueso <davidlohr@xxxxxx> --- ipc/msg.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/ipc/msg.c b/ipc/msg.c index b0d541d4..06e8aae 100644 --- a/ipc/msg.c +++ b/ipc/msg.c @@ -414,13 +414,13 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd, msq = container_of(ipcp, struct msg_queue, q_perm); + ipc_lock_object(&msq->q_perm); err = security_msg_queue_msgctl(msq, cmd); if (err) - goto out_unlock1; + goto out_unlock0; switch (cmd) { case IPC_RMID: - ipc_lock_object(&msq->q_perm); /* freeque unlocks the ipc object and rcu */ freeque(ns, ipcp); goto out_up; @@ -428,10 +428,9 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd, if (msqid64.msg_qbytes > ns->msg_ctlmnb && !capable(CAP_SYS_RESOURCE)) { err = -EPERM; - goto out_unlock1; + goto out_unlock0; } - ipc_lock_object(&msq->q_perm); err = ipc_update_perm(&msqid64.msg_perm, ipcp); if (err) goto out_unlock0; @@ -450,7 +449,6 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd, break; default: err = -EINVAL; - goto out_unlock1; } out_unlock0: @@ -542,9 +540,12 @@ static int msgctl_nolock(struct ipc_namespace *ns, int msqid, if (ipcperms(ns, &msq->q_perm, S_IRUGO)) goto out_unlock; + ipc_lock_object(&msq->q_perm); err = security_msg_queue_msgctl(msq, cmd); - if (err) + if (err) { + ipc_unlock_object(&msq->q_perm); goto out_unlock; + } kernel_to_ipc64_perm(&msq->q_perm, &tbuf.msg_perm); tbuf.msg_stime = msq->q_stime; @@ -556,6 +557,7 @@ static int msgctl_nolock(struct ipc_namespace *ns, int msqid, tbuf.msg_lspid = msq->q_lspid; tbuf.msg_lrpid = msq->q_lrpid; rcu_read_unlock(); + ipc_unlock_object(&msq->q_perm); if (copy_msqid_to_user(buf, &tbuf, version)) return -EFAULT; -- 1.7.11.7 -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html