diff options
Diffstat (limited to 'ipc')
| -rw-r--r-- | ipc/shm.c | 37 |
1 files changed, 29 insertions, 8 deletions
| @@ -208,15 +208,18 @@ static void shm_open(struct vm_area_struct *vma) | |||
| 208 | */ | 208 | */ |
| 209 | static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp) | 209 | static 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++; |
