aboutsummaryrefslogtreecommitdiffstats
path: root/ipc/msg.c
diff options
context:
space:
mode:
authorDavidlohr Bueso <davidlohr.bueso@hp.com>2013-07-08 19:01:16 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-09 13:33:27 -0400
commitac0ba20ea6f2201a1589d6dc26ad1a4f0f967bb8 (patch)
treebc3e2e4c4140f07ee1861b724ba7e1b295d7bbc6 /ipc/msg.c
parenta5001a0d9768568de5d613c3b3a5b9c7721299da (diff)
ipc,msg: make msgctl_nolock lockless
While the INFO cmd doesn't take the ipc lock, the STAT commands do acquire it unnecessarily. We can do the permissions and security checks only holding the rcu lock. This function now mimics semctl_nolock(). Signed-off-by: Davidlohr Bueso <davidlohr.bueso@hp.com> Cc: Andi Kleen <andi@firstfloor.org> Cc: Rik van Riel <riel@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'ipc/msg.c')
-rw-r--r--ipc/msg.c27
1 files changed, 17 insertions, 10 deletions
diff --git a/ipc/msg.c b/ipc/msg.c
index c53c13716064..c218328b5980 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -545,17 +545,25 @@ static int msgctl_nolock(struct ipc_namespace *ns, int msqid,
545 if (!buf) 545 if (!buf)
546 return -EFAULT; 546 return -EFAULT;
547 547
548 memset(&tbuf, 0, sizeof(tbuf));
549
550 rcu_read_lock();
548 if (cmd == MSG_STAT) { 551 if (cmd == MSG_STAT) {
549 msq = msg_lock(ns, msqid); 552 msq = msq_obtain_object(ns, msqid);
550 if (IS_ERR(msq)) 553 if (IS_ERR(msq)) {
551 return PTR_ERR(msq); 554 err = PTR_ERR(msq);
555 goto out_unlock;
556 }
552 success_return = msq->q_perm.id; 557 success_return = msq->q_perm.id;
553 } else { 558 } else {
554 msq = msg_lock_check(ns, msqid); 559 msq = msq_obtain_object_check(ns, msqid);
555 if (IS_ERR(msq)) 560 if (IS_ERR(msq)) {
556 return PTR_ERR(msq); 561 err = PTR_ERR(msq);
562 goto out_unlock;
563 }
557 success_return = 0; 564 success_return = 0;
558 } 565 }
566
559 err = -EACCES; 567 err = -EACCES;
560 if (ipcperms(ns, &msq->q_perm, S_IRUGO)) 568 if (ipcperms(ns, &msq->q_perm, S_IRUGO))
561 goto out_unlock; 569 goto out_unlock;
@@ -564,8 +572,6 @@ static int msgctl_nolock(struct ipc_namespace *ns, int msqid,
564 if (err) 572 if (err)
565 goto out_unlock; 573 goto out_unlock;
566 574
567 memset(&tbuf, 0, sizeof(tbuf));
568
569 kernel_to_ipc64_perm(&msq->q_perm, &tbuf.msg_perm); 575 kernel_to_ipc64_perm(&msq->q_perm, &tbuf.msg_perm);
570 tbuf.msg_stime = msq->q_stime; 576 tbuf.msg_stime = msq->q_stime;
571 tbuf.msg_rtime = msq->q_rtime; 577 tbuf.msg_rtime = msq->q_rtime;
@@ -575,7 +581,8 @@ static int msgctl_nolock(struct ipc_namespace *ns, int msqid,
575 tbuf.msg_qbytes = msq->q_qbytes; 581 tbuf.msg_qbytes = msq->q_qbytes;
576 tbuf.msg_lspid = msq->q_lspid; 582 tbuf.msg_lspid = msq->q_lspid;
577 tbuf.msg_lrpid = msq->q_lrpid; 583 tbuf.msg_lrpid = msq->q_lrpid;
578 msg_unlock(msq); 584 rcu_read_unlock();
585
579 if (copy_msqid_to_user(buf, &tbuf, version)) 586 if (copy_msqid_to_user(buf, &tbuf, version))
580 return -EFAULT; 587 return -EFAULT;
581 return success_return; 588 return success_return;
@@ -587,7 +594,7 @@ static int msgctl_nolock(struct ipc_namespace *ns, int msqid,
587 594
588 return err; 595 return err;
589out_unlock: 596out_unlock:
590 msg_unlock(msq); 597 rcu_read_unlock();
591 return err; 598 return err;
592} 599}
593 600