diff options
author | Davidlohr Bueso <davidlohr.bueso@hp.com> | 2013-08-01 16:32:02 +1000 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2013-08-01 16:32:02 +1000 |
commit | a711f80a220f804d98d97ec5c52404c754bd4fed (patch) | |
tree | 0afff80f52dc5dc294e2701d61719225bc4a0bcd /ipc | |
parent | db14d8a32c8cd0426999e0930e7128126ca1b2f0 (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.
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>
Diffstat (limited to 'ipc')
-rw-r--r-- | ipc/shm.c | 19 |
1 files changed, 12 insertions, 7 deletions
diff --git a/ipc/shm.c b/ipc/shm.c index ce357f4f70b9..ccc57999b570 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -882,27 +882,31 @@ static int shmctl_nolock(struct ipc_namespace *ns, int shmid, struct shmid64_ds tbuf; int result; + rcu_read_lock(); if (cmd == SHM_STAT) { - shp = shm_lock(ns, shmid); + shp = shm_obtain_object(ns, shmid); if (IS_ERR(shp)) { err = PTR_ERR(shp); - goto out; + goto out_unlock; } result = shp->shm_perm.id; } else { - shp = shm_lock_check(ns, shmid); + shp = shm_obtain_object_check(ns, shmid); if (IS_ERR(shp)) { err = PTR_ERR(shp); - goto out; + goto out_unlock; } result = 0; } + err = -EACCES; if (ipcperms(ns, &shp->shm_perm, S_IRUGO)) goto out_unlock; + err = security_shm_shmctl(shp, cmd); if (err) goto out_unlock; + memset(&tbuf, 0, sizeof(tbuf)); kernel_to_ipc64_perm(&shp->shm_perm, &tbuf.shm_perm); tbuf.shm_segsz = shp->shm_segsz; @@ -912,8 +916,9 @@ static int shmctl_nolock(struct ipc_namespace *ns, int shmid, tbuf.shm_cpid = shp->shm_cprid; tbuf.shm_lpid = shp->shm_lprid; tbuf.shm_nattch = shp->shm_nattch; - shm_unlock(shp); - if(copy_shmid_to_user (buf, &tbuf, version)) + rcu_read_unlock(); + + if (copy_shmid_to_user (buf, &tbuf, version)) err = -EFAULT; else err = result; @@ -924,7 +929,7 @@ static int shmctl_nolock(struct ipc_namespace *ns, int shmid, } out_unlock: - shm_unlock(shp); + rcu_read_unlock(); out: return err; } |