| From c2c737a0461e61a34676bd0bd1bc1a70a1b4e396 Mon Sep 17 00:00:00 2001 |
| From: Davidlohr Bueso <davidlohr.bueso@hp.com> |
| Date: Wed, 11 Sep 2013 14:26:23 -0700 |
| Subject: ipc,shm: shorten critical region for shmat |
| |
| From: Davidlohr Bueso <davidlohr.bueso@hp.com> |
| |
| commit c2c737a0461e61a34676bd0bd1bc1a70a1b4e396 upstream. |
| |
| Similar to other system calls, acquire the kern_ipc_perm lock after doing |
| the initial permission and security checks. |
| |
| [sasha.levin@oracle.com: dont leave do_shmat with rcu lock held] |
| 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: Sasha Levin <sasha.levin@oracle.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> |
| |
| --- |
| ipc/shm.c | 14 ++++++++++---- |
| 1 file changed, 10 insertions(+), 4 deletions(-) |
| |
| --- a/ipc/shm.c |
| +++ b/ipc/shm.c |
| @@ -19,6 +19,9 @@ |
| * namespaces support |
| * OpenVZ, SWsoft Inc. |
| * Pavel Emelianov <xemul@openvz.org> |
| + * |
| + * Better ipc lock (kern_ipc_perm.lock) handling |
| + * Davidlohr Bueso <davidlohr.bueso@hp.com>, June 2013. |
| */ |
| |
| #include <linux/slab.h> |
| @@ -1086,10 +1089,11 @@ long do_shmat(int shmid, char __user *sh |
| * additional creator id... |
| */ |
| ns = current->nsproxy->ipc_ns; |
| - shp = shm_lock_check(ns, shmid); |
| + rcu_read_lock(); |
| + shp = shm_obtain_object_check(ns, shmid); |
| if (IS_ERR(shp)) { |
| err = PTR_ERR(shp); |
| - goto out; |
| + goto out_unlock; |
| } |
| |
| err = -EACCES; |
| @@ -1100,11 +1104,13 @@ long do_shmat(int shmid, char __user *sh |
| if (err) |
| goto out_unlock; |
| |
| + ipc_lock_object(&shp->shm_perm); |
| path = shp->shm_file->f_path; |
| path_get(&path); |
| shp->shm_nattch++; |
| size = i_size_read(path.dentry->d_inode); |
| - shm_unlock(shp); |
| + ipc_unlock_object(&shp->shm_perm); |
| + rcu_read_unlock(); |
| |
| err = -ENOMEM; |
| sfd = kzalloc(sizeof(*sfd), GFP_KERNEL); |
| @@ -1175,7 +1181,7 @@ out_nattch: |
| return err; |
| |
| out_unlock: |
| - shm_unlock(shp); |
| + rcu_read_unlock(); |
| out: |
| return err; |
| } |