Index: sys/vm/vm_mmap.c =================================================================== --- sys/vm/vm_mmap.c +++ sys/vm/vm_mmap.c @@ -107,6 +107,9 @@ static int imply_prot_max = 0; SYSCTL_INT(_vm, OID_AUTO, imply_prot_max, CTLFLAG_RWTUN, &imply_prot_max, 0, "Imply maximum page protections in mmap() when none are specified"); +static bool allow_wx = true; +SYSCTL_BOOL(_vm, OID_AUTO, allow_wx, CTLFLAG_RWTUN, + &allow_wx, 0, "Allow pages to be mapped writable and executable"); #ifdef MAP_32BIT #define MAP_32BIT_MAX_ADDR ((vm_offset_t)1 << 31) @@ -212,6 +215,15 @@ return (kern_mmap_req(td, &mr)); } +static inline bool +allow_prot(struct proc *p, int prot) +{ + if ((prot & (PROT_WRITE | PROT_EXEC)) == (PROT_WRITE | PROT_EXEC) && + allow_wx == 0 && (p->p_fctl0 & NT_FREEBSD_FCTL_WXNEEDED) == 0) + return (false); + return (true); +} + int kern_mmap_req(struct thread *td, const struct mmap_req *mrp) { @@ -240,6 +252,8 @@ prot = PROT_EXTRACT(prot); if (max_prot != 0 && (max_prot & prot) != prot) return (ENOTSUP); + if (!allow_prot(td->td_proc, prot)) + return (ENOTSUP); p = td->td_proc; @@ -671,6 +685,8 @@ #endif if (addr + size < addr) return (EINVAL); + if (!allow_prot(td->td_proc, prot)) + return (ENOTSUP); vm_error = KERN_SUCCESS; if (max_prot != 0) {