Commit dafeda2a919bae062d63df18cfbe75672f86e54b

Authored by Davidlohr Bueso
Committed by Greg Kroah-Hartman
1 parent 24fc1afb6d

ipc,shm: introduce shmctl_nolock

commit 68eccc1dc345539d589ae78ee43b835c1a06a134 upstream.

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>
Cc: Mike Galbraith <efault@gmx.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Showing 1 changed file with 39 additions and 18 deletions Side-by-side Diff

... ... @@ -827,29 +827,24 @@
827 827 return err;
828 828 }
829 829  
830   -SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
  830 +static int shmctl_nolock(struct ipc_namespace *ns, int shmid,
  831 + int cmd, int version, void __user *buf)
831 832 {
  833 + int err;
832 834 struct shmid_kernel *shp;
833   - int err, version;
834   - struct ipc_namespace *ns;
835 835  
836   - if (cmd < 0 || shmid < 0) {
837   - err = -EINVAL;
838   - goto out;
  836 + /* preliminary security checks for *_INFO */
  837 + if (cmd == IPC_INFO || cmd == SHM_INFO) {
  838 + err = security_shm_shmctl(NULL, cmd);
  839 + if (err)
  840 + return err;
839 841 }
840 842  
841   - version = ipc_parse_version(&cmd);
842   - ns = current->nsproxy->ipc_ns;
843   -
844   - switch (cmd) { /* replace with proc interface ? */
  843 + switch (cmd) {
845 844 case IPC_INFO:
846 845 {
847 846 struct shminfo64 shminfo;
848 847  
849   - err = security_shm_shmctl(NULL, cmd);
850   - if (err)
851   - return err;
852   -
853 848 memset(&shminfo, 0, sizeof(shminfo));
854 849 shminfo.shmmni = shminfo.shmseg = ns->shm_ctlmni;
855 850 shminfo.shmmax = ns->shm_ctlmax;
... ... @@ -871,10 +866,6 @@
871 866 {
872 867 struct shm_info shm_info;
873 868  
874   - err = security_shm_shmctl(NULL, cmd);
875   - if (err)
876   - return err;
877   -
878 869 memset(&shm_info, 0, sizeof(shm_info));
879 870 down_read(&shm_ids(ns).rw_mutex);
880 871 shm_info.used_ids = shm_ids(ns).in_use;
... ... @@ -935,6 +926,36 @@
935 926 err = result;
936 927 goto out;
937 928 }
  929 + default:
  930 + return -EINVAL;
  931 + }
  932 +
  933 +out_unlock:
  934 + shm_unlock(shp);
  935 +out:
  936 + return err;
  937 +}
  938 +
  939 +SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
  940 +{
  941 + struct shmid_kernel *shp;
  942 + int err, version;
  943 + struct ipc_namespace *ns;
  944 +
  945 + if (cmd < 0 || shmid < 0) {
  946 + err = -EINVAL;
  947 + goto out;
  948 + }
  949 +
  950 + version = ipc_parse_version(&cmd);
  951 + ns = current->nsproxy->ipc_ns;
  952 +
  953 + switch (cmd) {
  954 + case IPC_INFO:
  955 + case SHM_INFO:
  956 + case SHM_STAT:
  957 + case IPC_STAT:
  958 + return shmctl_nolock(ns, shmid, cmd, version, buf);
938 959 case SHM_LOCK:
939 960 case SHM_UNLOCK:
940 961 {