aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavidlohr Bueso <davidlohr.bueso@hp.com>2013-09-11 17:26:18 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-11 18:59:39 -0400
commit68eccc1dc345539d589ae78ee43b835c1a06a134 (patch)
tree16943d2674537a5d13a14794763a3df7e51411ab
parent3b1c4ad37741e53804ffe0a30dd01e08b2ab6241 (diff)
ipc,shm: introduce shmctl_nolock
Similar to semctl and msgctl, when calling msgctl, the *_INFO and *_STAT commands can be performed without acquiring the ipc object. Add a shmctl_nolock() function and move the logic of *_INFO and *_STAT out of msgctl(). Since we are just moving functionality, this change still takes the lock and it will be properly lockless in the next patch. 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>
-rw-r--r--ipc/shm.c57
1 files changed, 39 insertions, 18 deletions
diff --git a/ipc/shm.c b/ipc/shm.c
index 22cffd78dbb1..3e123987f054 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -820,29 +820,24 @@ out_up:
820 return err; 820 return err;
821} 821}
822 822
823SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf) 823static int shmctl_nolock(struct ipc_namespace *ns, int shmid,
824 int cmd, int version, void __user *buf)
824{ 825{
826 int err;
825 struct shmid_kernel *shp; 827 struct shmid_kernel *shp;
826 int err, version;
827 struct ipc_namespace *ns;
828 828
829 if (cmd < 0 || shmid < 0) { 829 /* preliminary security checks for *_INFO */
830 err = -EINVAL; 830 if (cmd == IPC_INFO || cmd == SHM_INFO) {
831 goto out; 831 err = security_shm_shmctl(NULL, cmd);
832 if (err)
833 return err;
832 } 834 }
833 835
834 version = ipc_parse_version(&cmd); 836 switch (cmd) {
835 ns = current->nsproxy->ipc_ns;
836
837 switch (cmd) { /* replace with proc interface ? */
838 case IPC_INFO: 837 case IPC_INFO:
839 { 838 {
840 struct shminfo64 shminfo; 839 struct shminfo64 shminfo;
841 840
842 err = security_shm_shmctl(NULL, cmd);
843 if (err)
844 return err;
845
846 memset(&shminfo, 0, sizeof(shminfo)); 841 memset(&shminfo, 0, sizeof(shminfo));
847 shminfo.shmmni = shminfo.shmseg = ns->shm_ctlmni; 842 shminfo.shmmni = shminfo.shmseg = ns->shm_ctlmni;
848 shminfo.shmmax = ns->shm_ctlmax; 843 shminfo.shmmax = ns->shm_ctlmax;
@@ -864,10 +859,6 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
864 { 859 {
865 struct shm_info shm_info; 860 struct shm_info shm_info;
866 861
867 err = security_shm_shmctl(NULL, cmd);
868 if (err)
869 return err;
870
871 memset(&shm_info, 0, sizeof(shm_info)); 862 memset(&shm_info, 0, sizeof(shm_info));
872 down_read(&shm_ids(ns).rw_mutex); 863 down_read(&shm_ids(ns).rw_mutex);
873 shm_info.used_ids = shm_ids(ns).in_use; 864 shm_info.used_ids = shm_ids(ns).in_use;
@@ -928,6 +919,36 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
928 err = result; 919 err = result;
929 goto out; 920 goto out;
930 } 921 }
922 default:
923 return -EINVAL;
924 }
925
926out_unlock:
927 shm_unlock(shp);
928out:
929 return err;
930}
931
932SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
933{
934 struct shmid_kernel *shp;
935 int err, version;
936 struct ipc_namespace *ns;
937
938 if (cmd < 0 || shmid < 0) {
939 err = -EINVAL;
940 goto out;
941 }
942
943 version = ipc_parse_version(&cmd);
944 ns = current->nsproxy->ipc_ns;
945
946 switch (cmd) {
947 case IPC_INFO:
948 case SHM_INFO:
949 case SHM_STAT:
950 case IPC_STAT:
951 return shmctl_nolock(ns, shmid, cmd, version, buf);
931 case SHM_LOCK: 952 case SHM_LOCK:
932 case SHM_UNLOCK: 953 case SHM_UNLOCK:
933 { 954 {