int exec_sigcode_map(struct proc *p, struct emul *e) { vsize_t sz; sz = (vaddr_t)e->e_esigcode - (vaddr_t)e->e_sigcode; /* * If we don't have a sigobject for this emulation, create one. * * sigobject is an anonymous memory object (just like SYSV shared * memory) that we keep a permanent reference to and that we map * in all processes that need this sigcode. The creation is simple, * we create an object, add a permanent reference to it, map it in * kernel space, copy out the sigcode to it and unmap it. * Then we map it with PROT_READ|PROT_EXEC into the process just * the way sys_mmap would map it. */ if (e->e_sigobject == NULL) { vaddr_t va; int r; e->e_sigobject = uao_create(sz, 0); uao_reference(e->e_sigobject); /* permanent reference */ va = vm_map_min(kernel_map); /* hint */ if ((r = uvm_map(kernel_map, &va, round_page(sz), e->e_sigobject, 0, 0, UVM_MAPFLAG(UVM_PROT_RW, UVM_PROT_RW, UVM_INH_SHARE, UVM_ADV_RANDOM, 0)))) { uao_detach(e->e_sigobject); return (ENOMEM); } memcpy((void *)va, e->e_sigcode, sz); uvm_unmap(kernel_map, va, va + round_page(sz)); } /* Just a hint to uvm_mmap where to put it. */ p->p_sigcode = uvm_map_hint(p, VM_PROT_READ|VM_PROT_EXECUTE); uao_reference(e->e_sigobject); if (uvm_map(&p->p_vmspace->vm_map, &p->p_sigcode, round_page(sz), e->e_sigobject, 0, 0, UVM_MAPFLAG(UVM_PROT_RX, UVM_PROT_RX, UVM_INH_SHARE, UVM_ADV_RANDOM, 0))) { uao_detach(e->e_sigobject); return (ENOMEM); } return (0); }
int exec_sigcode_map(struct process *pr, struct emul *e) { vsize_t sz; sz = (vaddr_t)e->e_esigcode - (vaddr_t)e->e_sigcode; /* * If we don't have a sigobject for this emulation, create one. * * sigobject is an anonymous memory object (just like SYSV shared * memory) that we keep a permanent reference to and that we map * in all processes that need this sigcode. The creation is simple, * we create an object, add a permanent reference to it, map it in * kernel space, copy out the sigcode to it and unmap it. * Then we map it with PROT_READ|PROT_EXEC into the process just * the way sys_mmap would map it. */ if (e->e_sigobject == NULL) { vaddr_t va; int r; e->e_sigobject = uao_create(sz, 0); uao_reference(e->e_sigobject); /* permanent reference */ if ((r = uvm_map(kernel_map, &va, round_page(sz), e->e_sigobject, 0, 0, UVM_MAPFLAG(PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE, MAP_INHERIT_SHARE, MADV_RANDOM, 0)))) { uao_detach(e->e_sigobject); return (ENOMEM); } memcpy((void *)va, e->e_sigcode, sz); uvm_unmap(kernel_map, va, va + round_page(sz)); } pr->ps_sigcode = 0; /* no hint */ uao_reference(e->e_sigobject); if (uvm_map(&pr->ps_vmspace->vm_map, &pr->ps_sigcode, round_page(sz), e->e_sigobject, 0, 0, UVM_MAPFLAG(PROT_READ | PROT_EXEC, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_INHERIT_COPY, MADV_RANDOM, UVM_FLAG_COPYONW))) { uao_detach(e->e_sigobject); return (ENOMEM); } return (0); }
int sys_shmat(struct proc *p, void *v, register_t *retval) { struct sys_shmat_args /* { syscallarg(int) shmid; syscallarg(const void *) shmaddr; syscallarg(int) shmflg; } */ *uap = v; int error, i, flags; struct ucred *cred = p->p_ucred; struct shmid_ds *shmseg; struct shmmap_head *shmmap_h; struct shmmap_state *shmmap_s; struct shm_handle *shm_handle; vaddr_t attach_va; vm_prot_t prot; vsize_t size; shmmap_h = (struct shmmap_head *)p->p_vmspace->vm_shm; if (shmmap_h == NULL) { size = sizeof(int) + shminfo.shmseg * sizeof(struct shmmap_state); shmmap_h = malloc(size, M_SHM, M_WAITOK); shmmap_h->shmseg = shminfo.shmseg; for (i = 0, shmmap_s = shmmap_h->state; i < shmmap_h->shmseg; i++, shmmap_s++) shmmap_s->shmid = -1; p->p_vmspace->vm_shm = (caddr_t)shmmap_h; } shmseg = shm_find_segment_by_shmid(SCARG(uap, shmid)); if (shmseg == NULL) return (EINVAL); error = ipcperm(cred, &shmseg->shm_perm, (SCARG(uap, shmflg) & SHM_RDONLY) ? IPC_R : IPC_R|IPC_W); if (error) return (error); for (i = 0, shmmap_s = shmmap_h->state; i < shmmap_h->shmseg; i++) { if (shmmap_s->shmid == -1) break; shmmap_s++; } if (i >= shmmap_h->shmseg) return (EMFILE); size = round_page(shmseg->shm_segsz); prot = VM_PROT_READ; if ((SCARG(uap, shmflg) & SHM_RDONLY) == 0) prot |= VM_PROT_WRITE; flags = MAP_ANON | MAP_SHARED; if (SCARG(uap, shmaddr)) { flags |= MAP_FIXED; if (SCARG(uap, shmflg) & SHM_RND) attach_va = (vaddr_t)SCARG(uap, shmaddr) & ~(SHMLBA-1); else if (((vaddr_t)SCARG(uap, shmaddr) & (SHMLBA-1)) == 0) attach_va = (vaddr_t)SCARG(uap, shmaddr); else return (EINVAL); } else attach_va = 0; shm_handle = shmseg->shm_internal; uao_reference(shm_handle->shm_object); error = uvm_map(&p->p_vmspace->vm_map, &attach_va, size, shm_handle->shm_object, 0, 0, UVM_MAPFLAG(prot, prot, UVM_INH_SHARE, UVM_ADV_RANDOM, 0)); if (error) { uao_detach(shm_handle->shm_object); return (error); } shmmap_s->va = attach_va; shmmap_s->shmid = SCARG(uap, shmid); shmseg->shm_lpid = p->p_p->ps_pid; shmseg->shm_atime = time_second; shmseg->shm_nattch++; *retval = attach_va; return (0); }