Skip to content

Commit 68eccc1

Browse files
Davidlohr Buesotorvalds
authored andcommitted
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>
1 parent 3b1c4ad commit 68eccc1

File tree

1 file changed

+39
-18
lines changed

1 file changed

+39
-18
lines changed

ipc/shm.c

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -820,29 +820,24 @@ static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd,
820820
return err;
821821
}
822822

823-
SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
823+
static int shmctl_nolock(struct ipc_namespace *ns, int shmid,
824+
int cmd, int version, void __user *buf)
824825
{
826+
int err;
825827
struct shmid_kernel *shp;
826-
int err, version;
827-
struct ipc_namespace *ns;
828828

829-
if (cmd < 0 || shmid < 0) {
830-
err = -EINVAL;
831-
goto out;
829+
/* preliminary security checks for *_INFO */
830+
if (cmd == IPC_INFO || cmd == SHM_INFO) {
831+
err = security_shm_shmctl(NULL, cmd);
832+
if (err)
833+
return err;
832834
}
833835

834-
version = ipc_parse_version(&cmd);
835-
ns = current->nsproxy->ipc_ns;
836-
837-
switch (cmd) { /* replace with proc interface ? */
836+
switch (cmd) {
838837
case IPC_INFO:
839838
{
840839
struct shminfo64 shminfo;
841840

842-
err = security_shm_shmctl(NULL, cmd);
843-
if (err)
844-
return err;
845-
846841
memset(&shminfo, 0, sizeof(shminfo));
847842
shminfo.shmmni = shminfo.shmseg = ns->shm_ctlmni;
848843
shminfo.shmmax = ns->shm_ctlmax;
@@ -864,10 +859,6 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
864859
{
865860
struct shm_info shm_info;
866861

867-
err = security_shm_shmctl(NULL, cmd);
868-
if (err)
869-
return err;
870-
871862
memset(&shm_info, 0, sizeof(shm_info));
872863
down_read(&shm_ids(ns).rw_mutex);
873864
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)
928919
err = result;
929920
goto out;
930921
}
922+
default:
923+
return -EINVAL;
924+
}
925+
926+
out_unlock:
927+
shm_unlock(shp);
928+
out:
929+
return err;
930+
}
931+
932+
SYSCALL_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);
931952
case SHM_LOCK:
932953
case SHM_UNLOCK:
933954
{

0 commit comments

Comments
 (0)