Changeset View
Changeset View
Standalone View
Standalone View
sys/vm/vm_mmap.c
Show First 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | |||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/capsicum.h> | #include <sys/capsicum.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/lock.h> | #include <sys/lock.h> | ||||
#include <sys/mutex.h> | #include <sys/mutex.h> | ||||
#include <sys/sysproto.h> | #include <sys/sysproto.h> | ||||
#include <sys/filedesc.h> | #include <sys/filedesc.h> | ||||
#include <sys/elf.h> | |||||
emaste: can this go in alpha order, other misordered headers notwithstanding? | |||||
kibAuthorUnsubmitted Done Inline ActionsNot sure what would be the right place then. Moved before filedesc.h. kib: Not sure what would be the right place then. Moved before filedesc.h. | |||||
#include <sys/priv.h> | #include <sys/priv.h> | ||||
#include <sys/proc.h> | #include <sys/proc.h> | ||||
#include <sys/procctl.h> | #include <sys/procctl.h> | ||||
#include <sys/racct.h> | #include <sys/racct.h> | ||||
#include <sys/resource.h> | #include <sys/resource.h> | ||||
#include <sys/resourcevar.h> | #include <sys/resourcevar.h> | ||||
#include <sys/rwlock.h> | #include <sys/rwlock.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
▲ Show 20 Lines • Show All 110 Lines • ▼ Show 20 Lines | |||||
sys_mmap(struct thread *td, struct mmap_args *uap) | sys_mmap(struct thread *td, struct mmap_args *uap) | ||||
{ | { | ||||
return (kern_mmap(td, (uintptr_t)uap->addr, uap->len, uap->prot, | return (kern_mmap(td, (uintptr_t)uap->addr, uap->len, uap->prot, | ||||
uap->flags, uap->fd, uap->pos)); | uap->flags, uap->fd, uap->pos)); | ||||
} | } | ||||
int | int | ||||
kern_mmap_maxprot(struct proc *p, int prot) | |||||
{ | |||||
if ((p->p_flag2 & P2_PROTMAX_DISABLE) != 0 || | |||||
(p->p_fctl0 & NT_FREEBSD_FCTL_PROTMAX_DISABLE) != 0) | |||||
return (_PROT_ALL); | |||||
if (((p->p_flag2 & P2_PROTMAX_ENABLE) != 0 || imply_prot_max) && | |||||
prot != PROT_NONE) | |||||
return (prot); | |||||
return (_PROT_ALL); | |||||
} | |||||
int | |||||
kern_mmap(struct thread *td, uintptr_t addr0, size_t len, int prot, int flags, | kern_mmap(struct thread *td, uintptr_t addr0, size_t len, int prot, int flags, | ||||
int fd, off_t pos) | int fd, off_t pos) | ||||
{ | { | ||||
struct vmspace *vms; | struct vmspace *vms; | ||||
struct file *fp; | struct file *fp; | ||||
struct proc *p; | |||||
vm_offset_t addr; | vm_offset_t addr; | ||||
vm_size_t pageoff, size; | vm_size_t pageoff, size; | ||||
vm_prot_t cap_maxprot; | vm_prot_t cap_maxprot; | ||||
int align, error, max_prot; | int align, error, max_prot; | ||||
cap_rights_t rights; | cap_rights_t rights; | ||||
if ((prot & ~(_PROT_ALL | PROT_MAX(_PROT_ALL))) != 0) | if ((prot & ~(_PROT_ALL | PROT_MAX(_PROT_ALL))) != 0) | ||||
return (EINVAL); | return (EINVAL); | ||||
max_prot = PROT_MAX_EXTRACT(prot); | max_prot = PROT_MAX_EXTRACT(prot); | ||||
prot = PROT_EXTRACT(prot); | prot = PROT_EXTRACT(prot); | ||||
if (max_prot != 0 && (max_prot & prot) != prot) | if (max_prot != 0 && (max_prot & prot) != prot) | ||||
return (EINVAL); | return (EINVAL); | ||||
p = td->td_proc; | |||||
/* | /* | ||||
* Always honor PROT_MAX if set. If not, default to all | * Always honor PROT_MAX if set. If not, default to all | ||||
* permissions unless we're implying maximum permissions. | * permissions unless we're implying maximum permissions. | ||||
* | |||||
* XXX: should be tunable per process and ABI. | |||||
*/ | */ | ||||
if (max_prot == 0) | if (max_prot == 0) | ||||
max_prot = (imply_prot_max && prot != PROT_NONE) ? | max_prot = kern_mmap_maxprot(p, prot); | ||||
prot : _PROT_ALL; | |||||
vms = td->td_proc->p_vmspace; | vms = p->p_vmspace; | ||||
fp = NULL; | fp = NULL; | ||||
AUDIT_ARG_FD(fd); | AUDIT_ARG_FD(fd); | ||||
addr = addr0; | addr = addr0; | ||||
/* | /* | ||||
* Ignore old flags that used to be defined but did not do anything. | * Ignore old flags that used to be defined but did not do anything. | ||||
*/ | */ | ||||
flags &= ~(MAP_RESERVED0020 | MAP_RESERVED0040); | flags &= ~(MAP_RESERVED0020 | MAP_RESERVED0040); | ||||
/* | /* | ||||
* Enforce the constraints. | * Enforce the constraints. | ||||
* Mapping of length 0 is only allowed for old binaries. | * Mapping of length 0 is only allowed for old binaries. | ||||
* Anonymous mapping shall specify -1 as filedescriptor and | * Anonymous mapping shall specify -1 as filedescriptor and | ||||
* zero position for new code. Be nice to ancient a.out | * zero position for new code. Be nice to ancient a.out | ||||
* binaries and correct pos for anonymous mapping, since old | * binaries and correct pos for anonymous mapping, since old | ||||
* ld.so sometimes issues anonymous map requests with non-zero | * ld.so sometimes issues anonymous map requests with non-zero | ||||
* pos. | * pos. | ||||
*/ | */ | ||||
if (!SV_CURPROC_FLAG(SV_AOUT)) { | if (!SV_CURPROC_FLAG(SV_AOUT)) { | ||||
if ((len == 0 && curproc->p_osrel >= P_OSREL_MAP_ANON) || | if ((len == 0 && p->p_osrel >= P_OSREL_MAP_ANON) || | ||||
((flags & MAP_ANON) != 0 && (fd != -1 || pos != 0))) | ((flags & MAP_ANON) != 0 && (fd != -1 || pos != 0))) | ||||
return (EINVAL); | return (EINVAL); | ||||
} else { | } else { | ||||
if ((flags & MAP_ANON) != 0) | if ((flags & MAP_ANON) != 0) | ||||
pos = 0; | pos = 0; | ||||
} | } | ||||
if (flags & MAP_STACK) { | if (flags & MAP_STACK) { | ||||
▲ Show 20 Lines • Show All 129 Lines • ▼ Show 20 Lines | if ((flags & MAP_SHARED) != 0) { | ||||
cap_rights_set(&rights, CAP_MMAP_W); | cap_rights_set(&rights, CAP_MMAP_W); | ||||
} | } | ||||
if (prot & PROT_EXEC) | if (prot & PROT_EXEC) | ||||
cap_rights_set(&rights, CAP_MMAP_X); | cap_rights_set(&rights, CAP_MMAP_X); | ||||
error = fget_mmap(td, fd, &rights, &cap_maxprot, &fp); | error = fget_mmap(td, fd, &rights, &cap_maxprot, &fp); | ||||
if (error != 0) | if (error != 0) | ||||
goto done; | goto done; | ||||
if ((flags & (MAP_SHARED | MAP_PRIVATE)) == 0 && | if ((flags & (MAP_SHARED | MAP_PRIVATE)) == 0 && | ||||
td->td_proc->p_osrel >= P_OSREL_MAP_FSTRICT) { | p->p_osrel >= P_OSREL_MAP_FSTRICT) { | ||||
error = EINVAL; | error = EINVAL; | ||||
goto done; | goto done; | ||||
} | } | ||||
/* This relies on VM_PROT_* matching PROT_*. */ | /* This relies on VM_PROT_* matching PROT_*. */ | ||||
error = fo_mmap(fp, &vms->vm_map, &addr, size, prot, | error = fo_mmap(fp, &vms->vm_map, &addr, size, prot, | ||||
max_prot & cap_maxprot, flags, pos, td); | max_prot & cap_maxprot, flags, pos, td); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,246 Lines • Show Last 20 Lines |
can this go in alpha order, other misordered headers notwithstanding?