aboutsummaryrefslogtreecommitdiffstats
path: root/ipc
diff options
context:
space:
mode:
Diffstat (limited to 'ipc')
-rw-r--r--ipc/shm.c37
1 files changed, 29 insertions, 8 deletions
diff --git a/ipc/shm.c b/ipc/shm.c
index d69739610fd4..7a51443a51d6 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
@@ -974,15 +977,25 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
974 ipc_lock_object(&shp->shm_perm); 977 ipc_lock_object(&shp->shm_perm);
975 if (!ns_capable(ns->user_ns, CAP_IPC_LOCK)) { 978 if (!ns_capable(ns->user_ns, CAP_IPC_LOCK)) {
976 kuid_t euid = current_euid(); 979 kuid_t euid = current_euid();
977 err = -EPERM;
978 if (!uid_eq(euid, shp->shm_perm.uid) && 980 if (!uid_eq(euid, shp->shm_perm.uid) &&
979 !uid_eq(euid, shp->shm_perm.cuid)) 981 !uid_eq(euid, shp->shm_perm.cuid)) {
982 err = -EPERM;
980 goto out_unlock0; 983 goto out_unlock0;
981 if (cmd == SHM_LOCK && !rlimit(RLIMIT_MEMLOCK)) 984 }
985 if (cmd == SHM_LOCK && !rlimit(RLIMIT_MEMLOCK)) {
986 err = -EPERM;
982 goto out_unlock0; 987 goto out_unlock0;
988 }
983 } 989 }
984 990
985 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
986 if (is_file_hugepages(shm_file)) 999 if (is_file_hugepages(shm_file))
987 goto out_unlock0; 1000 goto out_unlock0;
988 1001
@@ -1101,6 +1114,14 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr,
1101 goto out_unlock; 1114 goto out_unlock;
1102 1115
1103 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
1104 path = shp->shm_file->f_path; 1125 path = shp->shm_file->f_path;
1105 path_get(&path); 1126 path_get(&path);
1106 shp->shm_nattch++; 1127 shp->shm_nattch++;