int shmdt(struct proc *p, struct shmdt_args *uap, int32_t *retval) { #if CONFIG_MACF struct shmid_kernel *shmsegptr; #endif struct shmmap_state *shmmap_s; int i; int shmdtret = 0; AUDIT_ARG(svipc_addr, uap->shmaddr); SYSV_SHM_SUBSYS_LOCK(); if ((shmdtret = shminit())) { goto shmdt_out; } shmmap_s = (struct shmmap_state *)p->vm_shm; if (shmmap_s == NULL) { shmdtret = EINVAL; goto shmdt_out; } for (; shmmap_s->shmid != SHMID_SENTINEL; shmmap_s++) { if (SHMID_IS_VALID(shmmap_s->shmid) && shmmap_s->va == (mach_vm_offset_t)uap->shmaddr) { break; } } if (!SHMID_IS_VALID(shmmap_s->shmid)) { shmdtret = EINVAL; goto shmdt_out; } #if CONFIG_MACF /* * XXX: It might be useful to move this into the shm_delete_mapping * function */ shmsegptr = &shmsegs[IPCID_TO_IX(shmmap_s->shmid)]; shmdtret = mac_sysvshm_check_shmdt(kauth_cred_get(), shmsegptr); if (shmdtret) goto shmdt_out; #endif i = shm_delete_mapping(p, shmmap_s, 1); if (i == 0) *retval = 0; shmdtret = i; shmdt_out: SYSV_SHM_SUBSYS_UNLOCK(); return shmdtret; }
void shmexit(struct vmspace *vm) { struct shmmap_head *shmmap_h; struct shmmap_state *shmmap_s; int i; shmmap_h = (struct shmmap_head *)vm->vm_shm; if (shmmap_h == NULL) return; for (i = 0, shmmap_s = shmmap_h->state; i < shmmap_h->shmseg; i++, shmmap_s++) if (shmmap_s->shmid != -1) shm_delete_mapping(vm, shmmap_s); free(vm->vm_shm, M_SHM); vm->vm_shm = NULL; }
int sys_shmdt(struct proc *p, void *v, register_t *retval) { struct sys_shmdt_args /* { syscallarg(const void *) shmaddr; } */ *uap = v; struct shmmap_head *shmmap_h; struct shmmap_state *shmmap_s; int i; shmmap_h = (struct shmmap_head *)p->p_vmspace->vm_shm; if (shmmap_h == NULL) return (EINVAL); for (i = 0, shmmap_s = shmmap_h->state; i < shmmap_h->shmseg; i++, shmmap_s++) if (shmmap_s->shmid != -1 && shmmap_s->va == (vaddr_t)SCARG(uap, shmaddr)) break; if (i == shmmap_h->shmseg) return (EINVAL); return (shm_delete_mapping(p->p_vmspace, shmmap_s)); }