|
@@ -208,15 +208,18 @@ static void shm_open(struct vm_area_struct *vma)
|
|
|
*/
|
|
|
static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp)
|
|
|
{
|
|
|
+ struct file *shm_file;
|
|
|
+
|
|
|
+ shm_file = shp->shm_file;
|
|
|
+ shp->shm_file = NULL;
|
|
|
ns->shm_tot -= (shp->shm_segsz + PAGE_SIZE - 1) >> PAGE_SHIFT;
|
|
|
shm_rmid(ns, shp);
|
|
|
shm_unlock(shp);
|
|
|
- if (!is_file_hugepages(shp->shm_file))
|
|
|
- shmem_lock(shp->shm_file, 0, shp->mlock_user);
|
|
|
+ if (!is_file_hugepages(shm_file))
|
|
|
+ shmem_lock(shm_file, 0, shp->mlock_user);
|
|
|
else if (shp->mlock_user)
|
|
|
- user_shm_unlock(file_inode(shp->shm_file)->i_size,
|
|
|
- shp->mlock_user);
|
|
|
- fput (shp->shm_file);
|
|
|
+ user_shm_unlock(file_inode(shm_file)->i_size, shp->mlock_user);
|
|
|
+ fput(shm_file);
|
|
|
ipc_rcu_putref(shp, shm_rcu_free);
|
|
|
}
|
|
|
|
|
@@ -983,6 +986,13 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
|
|
|
}
|
|
|
|
|
|
shm_file = shp->shm_file;
|
|
|
+
|
|
|
+ /* check if shm_destroy() is tearing down shp */
|
|
|
+ if (shm_file == NULL) {
|
|
|
+ err = -EIDRM;
|
|
|
+ goto out_unlock0;
|
|
|
+ }
|
|
|
+
|
|
|
if (is_file_hugepages(shm_file))
|
|
|
goto out_unlock0;
|
|
|
|
|
@@ -1101,6 +1111,14 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr,
|
|
|
goto out_unlock;
|
|
|
|
|
|
ipc_lock_object(&shp->shm_perm);
|
|
|
+
|
|
|
+ /* check if shm_destroy() is tearing down shp */
|
|
|
+ if (shp->shm_file == NULL) {
|
|
|
+ ipc_unlock_object(&shp->shm_perm);
|
|
|
+ err = -EIDRM;
|
|
|
+ goto out_unlock;
|
|
|
+ }
|
|
|
+
|
|
|
path = shp->shm_file->f_path;
|
|
|
path_get(&path);
|
|
|
shp->shm_nattch++;
|