version 1.91.2.3, 2007/02/26 09:12:31 |
version 1.91.2.4, 2007/09/03 14:47:09 |
Line 89 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 89 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#define COMPAT_ZERODEV(dev) (0) |
#define COMPAT_ZERODEV(dev) (0) |
#endif |
#endif |
|
|
|
#define RANGE_TEST(addr, size, ismmap) \ |
|
do { \ |
|
vaddr_t vm_min_address = VM_MIN_ADDRESS; \ |
|
vaddr_t vm_max_address = VM_MAXUSER_ADDRESS; \ |
|
vaddr_t eaddr = addr + size; \ |
|
\ |
|
if (addr < vm_min_address) \ |
|
return EINVAL; \ |
|
if (eaddr > vm_max_address) \ |
|
return /*CONSTCOND*/ \ |
|
ismmap ? EFBIG : EINVAL; \ |
|
if (addr > eaddr) /* no wrapping! */ \ |
|
return /*CONSTCOND*/ \ |
|
ismmap ? EOVERFLOW : EINVAL; \ |
|
} while (/*CONSTCOND*/0) |
|
|
/* |
/* |
* unimplemented VM system calls: |
* unimplemented VM system calls: |
*/ |
*/ |
Line 282 sys_mmap(l, v, retval) |
|
Line 298 sys_mmap(l, v, retval) |
|
register_t *retval; |
register_t *retval; |
{ |
{ |
struct sys_mmap_args /* { |
struct sys_mmap_args /* { |
syscallarg(caddr_t) addr; |
syscallarg(void *) addr; |
syscallarg(size_t) len; |
syscallarg(size_t) len; |
syscallarg(int) prot; |
syscallarg(int) prot; |
syscallarg(int) flags; |
syscallarg(int) flags; |
Line 297 sys_mmap(l, v, retval) |
|
Line 313 sys_mmap(l, v, retval) |
|
vsize_t size, pageoff; |
vsize_t size, pageoff; |
vm_prot_t prot, maxprot; |
vm_prot_t prot, maxprot; |
int flags, fd; |
int flags, fd; |
vaddr_t vm_min_address = VM_MIN_ADDRESS, defaddr; |
vaddr_t defaddr; |
struct filedesc *fdp = p->p_fd; |
struct filedesc *fdp = p->p_fd; |
struct file *fp; |
struct file *fp; |
struct vnode *vp; |
struct vnode *vp; |
Line 332 sys_mmap(l, v, retval) |
|
Line 348 sys_mmap(l, v, retval) |
|
pos -= pageoff; |
pos -= pageoff; |
size += pageoff; /* add offset */ |
size += pageoff; /* add offset */ |
size = (vsize_t)round_page(size); /* round up */ |
size = (vsize_t)round_page(size); /* round up */ |
if ((ssize_t) size < 0) |
|
return (EINVAL); /* don't allow wrap */ |
|
|
|
/* |
/* |
* now check (MAP_FIXED) or get (!MAP_FIXED) the "addr" |
* now check (MAP_FIXED) or get (!MAP_FIXED) the "addr" |
*/ |
*/ |
|
|
if (flags & MAP_FIXED) { |
if (flags & MAP_FIXED) { |
|
|
/* ensure address and file offset are aligned properly */ |
/* ensure address and file offset are aligned properly */ |
Line 346 sys_mmap(l, v, retval) |
|
Line 359 sys_mmap(l, v, retval) |
|
if (addr & PAGE_MASK) |
if (addr & PAGE_MASK) |
return (EINVAL); |
return (EINVAL); |
|
|
if (VM_MAXUSER_ADDRESS > 0 && |
RANGE_TEST(addr, size, 1); |
(addr + size) > VM_MAXUSER_ADDRESS) |
|
return (EFBIG); |
|
if (vm_min_address > 0 && addr < vm_min_address) |
|
return (EINVAL); |
|
if (addr > addr + size) |
|
return (EOVERFLOW); /* no wrapping! */ |
|
|
|
} else if (addr == 0 || !(flags & MAP_TRYFIXED)) { |
} else if (addr == 0 || !(flags & MAP_TRYFIXED)) { |
|
|
Line 439 sys_mmap(l, v, retval) |
|
Line 446 sys_mmap(l, v, retval) |
|
|
|
maxprot = VM_PROT_EXECUTE; |
maxprot = VM_PROT_EXECUTE; |
|
|
#if NVERIEXEC > 0 |
|
/* |
|
* Check if the file can be executed indirectly. |
|
*/ |
|
if (veriexec_verify(l, vp, "(mmap)", VERIEXEC_INDIRECT, NULL)) { |
|
/* |
|
* Don't allow executable mappings if we can't |
|
* indirectly execute the file. |
|
*/ |
|
if (prot & VM_PROT_EXECUTE) |
|
return (EPERM); |
|
|
|
/* |
|
* Strip the executable bit from 'maxprot' to make sure |
|
* it can't be made executable later. |
|
*/ |
|
maxprot &= ~VM_PROT_EXECUTE; |
|
} |
|
#endif /* NVERIEXEC > 0 */ |
|
|
|
/* check read access */ |
/* check read access */ |
if (fp->f_flag & FREAD) |
if (fp->f_flag & FREAD) |
maxprot |= VM_PROT_READ; |
maxprot |= VM_PROT_READ; |
Line 520 sys_mmap(l, v, retval) |
|
Line 507 sys_mmap(l, v, retval) |
|
} |
} |
} |
} |
|
|
|
#if NVERIEXEC > 0 |
|
if (handle != NULL) { |
|
/* |
|
* Check if the file can be executed indirectly. |
|
* |
|
* XXX: This gives false warnings about "Incorrect access type" |
|
* XXX: if the mapping is not executable. Harmless, but will be |
|
* XXX: fixed as part of other changes. |
|
*/ |
|
if (veriexec_verify(l, handle, "(mmap)", VERIEXEC_INDIRECT, |
|
NULL)) { |
|
/* |
|
* Don't allow executable mappings if we can't |
|
* indirectly execute the file. |
|
*/ |
|
if (prot & VM_PROT_EXECUTE) |
|
return (EPERM); |
|
|
|
/* |
|
* Strip the executable bit from 'maxprot' to make sure |
|
* it can't be made executable later. |
|
*/ |
|
maxprot &= ~VM_PROT_EXECUTE; |
|
} |
|
} |
|
#endif /* NVERIEXEC > 0 */ |
|
|
#ifdef PAX_MPROTECT |
#ifdef PAX_MPROTECT |
pax_mprotect(l, &prot, &maxprot); |
pax_mprotect(l, &prot, &maxprot); |
#endif /* PAX_MPROTECT */ |
#endif /* PAX_MPROTECT */ |
|
|
sys___msync13(struct lwp *l, void *v, register_t *retval) |
sys___msync13(struct lwp *l, void *v, register_t *retval) |
{ |
{ |
struct sys___msync13_args /* { |
struct sys___msync13_args /* { |
syscallarg(caddr_t) addr; |
syscallarg(void *) addr; |
syscallarg(size_t) len; |
syscallarg(size_t) len; |
syscallarg(int) flags; |
syscallarg(int) flags; |
} */ *uap = v; |
} */ *uap = v; |
Line 581 sys___msync13(struct lwp *l, void *v, re |
|
Line 595 sys___msync13(struct lwp *l, void *v, re |
|
size += pageoff; |
size += pageoff; |
size = (vsize_t)round_page(size); |
size = (vsize_t)round_page(size); |
|
|
/* disallow wrap-around. */ |
RANGE_TEST(addr, size, 0); |
if (addr + size < addr) |
|
return (EINVAL); |
|
|
|
/* |
/* |
* get map |
* get map |
|
|
sys_munmap(struct lwp *l, void *v, register_t *retval) |
sys_munmap(struct lwp *l, void *v, register_t *retval) |
{ |
{ |
struct sys_munmap_args /* { |
struct sys_munmap_args /* { |
syscallarg(caddr_t) addr; |
syscallarg(void *) addr; |
syscallarg(size_t) len; |
syscallarg(size_t) len; |
} */ *uap = v; |
} */ *uap = v; |
struct proc *p = l->l_proc; |
struct proc *p = l->l_proc; |
vaddr_t addr; |
vaddr_t addr; |
vsize_t size, pageoff; |
vsize_t size, pageoff; |
struct vm_map *map; |
struct vm_map *map; |
vaddr_t vm_min_address = VM_MIN_ADDRESS; |
|
struct vm_map_entry *dead_entries; |
struct vm_map_entry *dead_entries; |
|
|
/* |
/* |
Line 664 sys_munmap(struct lwp *l, void *v, regis |
|
Line 675 sys_munmap(struct lwp *l, void *v, regis |
|
size += pageoff; |
size += pageoff; |
size = (vsize_t)round_page(size); |
size = (vsize_t)round_page(size); |
|
|
if ((int)size < 0) |
|
return (EINVAL); |
|
if (size == 0) |
if (size == 0) |
return (0); |
return (0); |
|
|
/* |
RANGE_TEST(addr, size, 0); |
* Check for illegal addresses. Watch out for address wrap... |
|
* Note that VM_*_ADDRESS are not constants due to casts (argh). |
|
*/ |
|
if (VM_MAXUSER_ADDRESS > 0 && addr + size > VM_MAXUSER_ADDRESS) |
|
return (EINVAL); |
|
if (vm_min_address > 0 && addr < vm_min_address) |
|
return (EINVAL); |
|
if (addr > addr + size) |
|
return (EINVAL); |
|
map = &p->p_vmspace->vm_map; |
map = &p->p_vmspace->vm_map; |
|
|
/* |
/* |
|
|
sys_mprotect(struct lwp *l, void *v, register_t *retval) |
sys_mprotect(struct lwp *l, void *v, register_t *retval) |
{ |
{ |
struct sys_mprotect_args /* { |
struct sys_mprotect_args /* { |
syscallarg(caddr_t) addr; |
syscallarg(void *) addr; |
syscallarg(size_t) len; |
syscallarg(size_t) len; |
syscallarg(int) prot; |
syscallarg(int) prot; |
} */ *uap = v; |
} */ *uap = v; |
Line 735 sys_mprotect(struct lwp *l, void *v, reg |
|
Line 736 sys_mprotect(struct lwp *l, void *v, reg |
|
size += pageoff; |
size += pageoff; |
size = round_page(size); |
size = round_page(size); |
|
|
|
RANGE_TEST(addr, size, 0); |
|
|
error = uvm_map_protect(&p->p_vmspace->vm_map, addr, addr + size, prot, |
error = uvm_map_protect(&p->p_vmspace->vm_map, addr, addr + size, prot, |
false); |
false); |
return error; |
return error; |
|
|
sys_minherit(struct lwp *l, void *v, register_t *retval) |
sys_minherit(struct lwp *l, void *v, register_t *retval) |
{ |
{ |
struct sys_minherit_args /* { |
struct sys_minherit_args /* { |
syscallarg(caddr_t) addr; |
syscallarg(void *) addr; |
syscallarg(int) len; |
syscallarg(int) len; |
syscallarg(int) inherit; |
syscallarg(int) inherit; |
} */ *uap = v; |
} */ *uap = v; |
Line 771 sys_minherit(struct lwp *l, void *v, reg |
|
Line 774 sys_minherit(struct lwp *l, void *v, reg |
|
size += pageoff; |
size += pageoff; |
size = (vsize_t)round_page(size); |
size = (vsize_t)round_page(size); |
|
|
if ((int)size < 0) |
RANGE_TEST(addr, size, 0); |
return (EINVAL); |
|
error = uvm_map_inherit(&p->p_vmspace->vm_map, addr, addr + size, |
error = uvm_map_inherit(&p->p_vmspace->vm_map, addr, addr + size, |
inherit); |
inherit); |
return error; |
return error; |
|
|
sys_madvise(struct lwp *l, void *v, register_t *retval) |
sys_madvise(struct lwp *l, void *v, register_t *retval) |
{ |
{ |
struct sys_madvise_args /* { |
struct sys_madvise_args /* { |
syscallarg(caddr_t) addr; |
syscallarg(void *) addr; |
syscallarg(size_t) len; |
syscallarg(size_t) len; |
syscallarg(int) behav; |
syscallarg(int) behav; |
} */ *uap = v; |
} */ *uap = v; |
Line 809 sys_madvise(struct lwp *l, void *v, regi |
|
Line 812 sys_madvise(struct lwp *l, void *v, regi |
|
size += pageoff; |
size += pageoff; |
size = (vsize_t)round_page(size); |
size = (vsize_t)round_page(size); |
|
|
if ((ssize_t)size <= 0) |
RANGE_TEST(addr, size, 0); |
return (EINVAL); |
|
|
|
switch (advice) { |
switch (advice) { |
case MADV_NORMAL: |
case MADV_NORMAL: |
Line 912 sys_mlock(struct lwp *l, void *v, regist |
|
Line 914 sys_mlock(struct lwp *l, void *v, regist |
|
size += pageoff; |
size += pageoff; |
size = (vsize_t)round_page(size); |
size = (vsize_t)round_page(size); |
|
|
/* disallow wrap-around. */ |
RANGE_TEST(addr, size, 0); |
if (addr + size < addr) |
|
return (EINVAL); |
|
|
|
if (atop(size) + uvmexp.wired > uvmexp.wiredmax) |
if (atop(size) + uvmexp.wired > uvmexp.wiredmax) |
return (EAGAIN); |
return (EAGAIN); |
Line 962 sys_munlock(struct lwp *l, void *v, regi |
|
Line 962 sys_munlock(struct lwp *l, void *v, regi |
|
size += pageoff; |
size += pageoff; |
size = (vsize_t)round_page(size); |
size = (vsize_t)round_page(size); |
|
|
/* disallow wrap-around. */ |
RANGE_TEST(addr, size, 0); |
if (addr + size < addr) |
|
return (EINVAL); |
|
|
|
error = uvm_map_pageable(&p->p_vmspace->vm_map, addr, addr+size, true, |
error = uvm_map_pageable(&p->p_vmspace->vm_map, addr, addr+size, true, |
0); |
0); |
Line 1115 uvm_mmap(map, addr, size, prot, maxprot, |
|
Line 1113 uvm_mmap(map, addr, size, prot, maxprot, |
|
return (EACCES); |
return (EACCES); |
|
|
if (vp->v_type != VCHR) { |
if (vp->v_type != VCHR) { |
error = VOP_MMAP(vp, 0, curlwp->l_cred, curlwp); |
error = VOP_MMAP(vp, prot, curlwp->l_cred, curlwp); |
if (error) { |
if (error) { |
return error; |
return error; |
} |
} |
|
vref(vp); |
uobj = uvn_attach((void *)vp, (flags & MAP_SHARED) ? |
uobj = &vp->v_uobj; |
maxprot : (maxprot & ~VM_PROT_WRITE)); |
|
|
|
/* XXX for now, attach doesn't gain a ref */ |
|
VREF(vp); |
|
|
|
/* |
/* |
* If the vnode is being mapped with PROT_EXEC, |
* If the vnode is being mapped with PROT_EXEC, |