aboutsummaryrefslogtreecommitdiffstats
path: root/ipc/shm.c
diff options
context:
space:
mode:
Diffstat (limited to 'ipc/shm.c')
-rw-r--r--ipc/shm.c28
1 files changed, 23 insertions, 5 deletions
diff --git a/ipc/shm.c b/ipc/shm.c
index 8ffae5807317..6dc55af8a29b 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -208,15 +208,18 @@ static void shm_open(struct vm_area_struct *vma)
208 */ 208 */
209static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp) 209static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp)
210{ 210{
211 struct file *shm_file;
212
213 shm_file = shp->shm_file;
214 shp->shm_file = NULL;
211 ns->shm_tot -= (shp->shm_segsz + PAGE_SIZE - 1) >> PAGE_SHIFT; 215 ns->shm_tot -= (shp->shm_segsz + PAGE_SIZE - 1) >> PAGE_SHIFT;
212 shm_rmid(ns, shp); 216 shm_rmid(ns, shp);
213 shm_unlock(shp); 217 shm_unlock(shp);
214 if (!is_file_hugepages(shp->shm_file)) 218 if (!is_file_hugepages(shm_file))
215 shmem_lock(shp->shm_file, 0, shp->mlock_user); 219 shmem_lock(shm_file, 0, shp->mlock_user);
216 else if (shp->mlock_user) 220 else if (shp->mlock_user)
217 user_shm_unlock(file_inode(shp->shm_file)->i_size, 221 user_shm_unlock(file_inode(shm_file)->i_size, shp->mlock_user);
218 shp->mlock_user); 222 fput(shm_file);
219 fput (shp->shm_file);
220 ipc_rcu_putref(shp, shm_rcu_free); 223 ipc_rcu_putref(shp, shm_rcu_free);
221} 224}
222 225
@@ -986,6 +989,13 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
986 } 989 }
987 990
988 shm_file = shp->shm_file; 991 shm_file = shp->shm_file;
992
993 /* check if shm_destroy() is tearing down shp */
994 if (shm_file == NULL) {
995 err = -EIDRM;
996 goto out_unlock0;
997 }
998
989 if (is_file_hugepages(shm_file)) 999 if (is_file_hugepages(shm_file))
990 goto out_unlock0; 1000 goto out_unlock0;
991 1001
@@ -1104,6 +1114,14 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr,
1104 goto out_unlock; 1114 goto out_unlock;
1105 1115
1106 ipc_lock_object(&shp->shm_perm); 1116 ipc_lock_object(&shp->shm_perm);
1117
1118 /* check if shm_destroy() is tearing down shp */
1119 if (shp->shm_file == NULL) {
1120 ipc_unlock_object(&shp->shm_perm);
1121 err = -EIDRM;
1122 goto out_unlock;
1123 }
1124
1107 path = shp->shm_file->f_path; 1125 path = shp->shm_file->f_path;
1108 path_get(&path); 1126 path_get(&path);
1109 shp->shm_nattch++; 1127 shp->shm_nattch++;