Commit dafeda2a919bae062d63df18cfbe75672f86e54b
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
ipc/shm.c
... | ... | @@ -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 | { |