aboutsummaryrefslogtreecommitdiffstats
path: root/ipc
diff options
context:
space:
mode:
authorDavidlohr Bueso <davidlohr.bueso@hp.com>2013-09-11 17:26:20 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-11 18:59:39 -0400
commitc97cb9ccab8c85428ec21eff690642ad2ce1fa8a (patch)
treec435476a079d3bff28ec8c67377227effba57ca9 /ipc
parent68eccc1dc345539d589ae78ee43b835c1a06a134 (diff)
ipc,shm: make shmctl_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. [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Davidlohr Bueso <davidlohr.bueso@hp.com> Tested-by: Sedat Dilek <sedat.dilek@gmail.com> Cc: Rik van Riel <riel@redhat.com> Cc: Manfred Spraul <manfred@colorfullife.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'ipc')
-rw-r--r--ipc/shm.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/ipc/shm.c b/ipc/shm.c
index 3e123987f054..a493639550d9 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -882,27 +882,31 @@ static int shmctl_nolock(struct ipc_namespace *ns, int shmid,
882 struct shmid64_ds tbuf; 882 struct shmid64_ds tbuf;
883 int result; 883 int result;
884 884
885 rcu_read_lock();
885 if (cmd == SHM_STAT) { 886 if (cmd == SHM_STAT) {
886 shp = shm_lock(ns, shmid); 887 shp = shm_obtain_object(ns, shmid);
887 if (IS_ERR(shp)) { 888 if (IS_ERR(shp)) {
888 err = PTR_ERR(shp); 889 err = PTR_ERR(shp);
889 goto out; 890 goto out_unlock;
890 } 891 }
891 result = shp->shm_perm.id; 892 result = shp->shm_perm.id;
892 } else { 893 } else {
893 shp = shm_lock_check(ns, shmid); 894 shp = shm_obtain_object_check(ns, shmid);
894 if (IS_ERR(shp)) { 895 if (IS_ERR(shp)) {
895 err = PTR_ERR(shp); 896 err = PTR_ERR(shp);
896 goto out; 897 goto out_unlock;
897 } 898 }
898 result = 0; 899 result = 0;
899 } 900 }
901
900 err = -EACCES; 902 err = -EACCES;
901 if (ipcperms(ns, &shp->shm_perm, S_IRUGO)) 903 if (ipcperms(ns, &shp->shm_perm, S_IRUGO))
902 goto out_unlock; 904 goto out_unlock;
905
903 err = security_shm_shmctl(shp, cmd); 906 err = security_shm_shmctl(shp, cmd);
904 if (err) 907 if (err)
905 goto out_unlock; 908 goto out_unlock;
909
906 memset(&tbuf, 0, sizeof(tbuf)); 910 memset(&tbuf, 0, sizeof(tbuf));
907 kernel_to_ipc64_perm(&shp->shm_perm, &tbuf.shm_perm); 911 kernel_to_ipc64_perm(&shp->shm_perm, &tbuf.shm_perm);
908 tbuf.shm_segsz = shp->shm_segsz; 912 tbuf.shm_segsz = shp->shm_segsz;
@@ -912,8 +916,9 @@ static int shmctl_nolock(struct ipc_namespace *ns, int shmid,
912 tbuf.shm_cpid = shp->shm_cprid; 916 tbuf.shm_cpid = shp->shm_cprid;
913 tbuf.shm_lpid = shp->shm_lprid; 917 tbuf.shm_lpid = shp->shm_lprid;
914 tbuf.shm_nattch = shp->shm_nattch; 918 tbuf.shm_nattch = shp->shm_nattch;
915 shm_unlock(shp); 919 rcu_read_unlock();
916 if(copy_shmid_to_user (buf, &tbuf, version)) 920
921 if (copy_shmid_to_user(buf, &tbuf, version))
917 err = -EFAULT; 922 err = -EFAULT;
918 else 923 else
919 err = result; 924 err = result;
@@ -924,7 +929,7 @@ static int shmctl_nolock(struct ipc_namespace *ns, int shmid,
924 } 929 }
925 930
926out_unlock: 931out_unlock:
927 shm_unlock(shp); 932 rcu_read_unlock();
928out: 933out:
929 return err; 934 return err;
930} 935}