Skip to content

Commit

Permalink
ipc,msg: shorten critical region in msgctl_down
Browse files Browse the repository at this point in the history
Instead of holding the ipc lock for the entire function, use the
ipcctl_pre_down_nolock and only acquire the lock for specific commands:
RMID and SET.

Signed-off-by: Davidlohr Bueso <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: Rik van Riel <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Davidlohr Bueso authored and torvalds committed Jul 9, 2013
1 parent 7b4cc5d commit 15724ec
Showing 1 changed file with 7 additions and 5 deletions.
12 changes: 7 additions & 5 deletions ipc/msg.c
Original file line number Diff line number Diff line change
Expand Up @@ -410,32 +410,33 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,
down_write(&msg_ids(ns).rw_mutex);
rcu_read_lock();

ipcp = ipcctl_pre_down(ns, &msg_ids(ns), msqid, cmd,
&msqid64.msg_perm, msqid64.msg_qbytes);
ipcp = ipcctl_pre_down_nolock(ns, &msg_ids(ns), msqid, cmd,
&msqid64.msg_perm, msqid64.msg_qbytes);
if (IS_ERR(ipcp)) {
err = PTR_ERR(ipcp);
/* the ipc lock is not held upon failure */
goto out_unlock1;
}

msq = container_of(ipcp, struct msg_queue, q_perm);

err = security_msg_queue_msgctl(msq, cmd);
if (err)
goto out_unlock0;
goto out_unlock1;

switch (cmd) {
case IPC_RMID:
ipc_lock_object(&msq->q_perm);
/* freeque unlocks the ipc object and rcu */
freeque(ns, ipcp);
goto out_up;
case IPC_SET:
if (msqid64.msg_qbytes > ns->msg_ctlmnb &&
!capable(CAP_SYS_RESOURCE)) {
err = -EPERM;
goto out_unlock0;
goto out_unlock1;
}

ipc_lock_object(&msq->q_perm);
err = ipc_update_perm(&msqid64.msg_perm, ipcp);
if (err)
goto out_unlock0;
Expand All @@ -454,6 +455,7 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,
break;
default:
err = -EINVAL;
goto out_unlock1;
}

out_unlock0:
Expand Down

0 comments on commit 15724ec

Please sign in to comment.