summaryrefslogtreecommitdiffstats
path: root/ipc/shm.c
diff options
context:
space:
mode:
authorDavidlohr Bueso <davidlohr.bueso@hp.com>2013-07-08 19:01:12 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-09 13:33:27 -0400
commit7b4cc5d8411bd4e9d61d8714f53859740cf830c2 (patch)
treeb95f3b875a5f4c927b0f27cc3c7ddcba5cc8e1e8 /ipc/shm.c
parentcf9d5d78d05bca96df7618dfc3a5ee4414dcae58 (diff)
ipc: move locking out of ipcctl_pre_down_nolock
This function currently acquires both the rw_mutex and the rcu lock on successful lookups, leaving the callers to explicitly unlock them, creating another two level locking situation. Make the callers (including those that still use ipcctl_pre_down()) explicitly lock and unlock the rwsem and rcu lock. 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/shm.c')
-rw-r--r--ipc/shm.c23
1 files changed, 17 insertions, 6 deletions
diff --git a/ipc/shm.c b/ipc/shm.c
index e7d51072d1c7..c6b4ad5ce3b7 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -757,31 +757,42 @@ static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd,
757 return -EFAULT; 757 return -EFAULT;
758 } 758 }
759 759
760 down_write(&shm_ids(ns).rw_mutex);
761 rcu_read_lock();
762
760 ipcp = ipcctl_pre_down(ns, &shm_ids(ns), shmid, cmd, 763 ipcp = ipcctl_pre_down(ns, &shm_ids(ns), shmid, cmd,
761 &shmid64.shm_perm, 0); 764 &shmid64.shm_perm, 0);
762 if (IS_ERR(ipcp)) 765 if (IS_ERR(ipcp)) {
763 return PTR_ERR(ipcp); 766 err = PTR_ERR(ipcp);
767 /* the ipc lock is not held upon failure */
768 goto out_unlock1;
769 }
764 770
765 shp = container_of(ipcp, struct shmid_kernel, shm_perm); 771 shp = container_of(ipcp, struct shmid_kernel, shm_perm);
766 772
767 err = security_shm_shmctl(shp, cmd); 773 err = security_shm_shmctl(shp, cmd);
768 if (err) 774 if (err)
769 goto out_unlock; 775 goto out_unlock0;
776
770 switch (cmd) { 777 switch (cmd) {
771 case IPC_RMID: 778 case IPC_RMID:
779 /* do_shm_rmid unlocks the ipc object and rcu */
772 do_shm_rmid(ns, ipcp); 780 do_shm_rmid(ns, ipcp);
773 goto out_up; 781 goto out_up;
774 case IPC_SET: 782 case IPC_SET:
775 err = ipc_update_perm(&shmid64.shm_perm, ipcp); 783 err = ipc_update_perm(&shmid64.shm_perm, ipcp);
776 if (err) 784 if (err)
777 goto out_unlock; 785 goto out_unlock0;
778 shp->shm_ctim = get_seconds(); 786 shp->shm_ctim = get_seconds();
779 break; 787 break;
780 default: 788 default:
781 err = -EINVAL; 789 err = -EINVAL;
782 } 790 }
783out_unlock: 791
784 shm_unlock(shp); 792out_unlock0:
793 ipc_unlock_object(&shp->shm_perm);
794out_unlock1:
795 rcu_read_unlock();
785out_up: 796out_up:
786 up_write(&shm_ids(ns).rw_mutex); 797 up_write(&shm_ids(ns).rw_mutex);
787 return err; 798 return err;