Home | History | Annotate | Line # | Download | only in kern
exec_subr.c revision 1.76.8.1
      1 /*	$NetBSD: exec_subr.c,v 1.76.8.1 2017/05/11 02:58:40 pgoyette Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1993, 1994, 1996 Christopher G. Demetriou
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *      This product includes software developed by Christopher G. Demetriou.
     18  * 4. The name of the author may not be used to endorse or promote products
     19  *    derived from this software without specific prior written permission
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 #include <sys/cdefs.h>
     34 __KERNEL_RCSID(0, "$NetBSD: exec_subr.c,v 1.76.8.1 2017/05/11 02:58:40 pgoyette Exp $");
     35 
     36 #include "opt_pax.h"
     37 
     38 #include <sys/param.h>
     39 #include <sys/systm.h>
     40 #include <sys/proc.h>
     41 #include <sys/kmem.h>
     42 #include <sys/vnode.h>
     43 #include <sys/filedesc.h>
     44 #include <sys/exec.h>
     45 #include <sys/mman.h>
     46 #include <sys/resourcevar.h>
     47 #include <sys/device.h>
     48 #include <sys/pax.h>
     49 
     50 #include <uvm/uvm_extern.h>
     51 
     52 #define	VMCMD_EVCNT_DECL(name)					\
     53 static struct evcnt vmcmd_ev_##name =				\
     54     EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "vmcmd", #name);	\
     55 EVCNT_ATTACH_STATIC(vmcmd_ev_##name)
     56 
     57 #define	VMCMD_EVCNT_INCR(name)					\
     58     vmcmd_ev_##name.ev_count++
     59 
     60 VMCMD_EVCNT_DECL(calls);
     61 VMCMD_EVCNT_DECL(extends);
     62 VMCMD_EVCNT_DECL(kills);
     63 
     64 #ifdef DEBUG_STACK
     65 #define DPRINTF(a) uprintf a
     66 #else
     67 #define DPRINTF(a)
     68 #endif
     69 
     70 /*
     71  * new_vmcmd():
     72  *	create a new vmcmd structure and fill in its fields based
     73  *	on function call arguments.  make sure objects ref'd by
     74  *	the vmcmd are 'held'.
     75  */
     76 
     77 void
     78 new_vmcmd(struct exec_vmcmd_set *evsp,
     79     int (*proc)(struct lwp * l, struct exec_vmcmd *),
     80     vsize_t len, vaddr_t addr, struct vnode *vp, u_long offset,
     81     u_int prot, int flags)
     82 {
     83 	struct exec_vmcmd *vcp;
     84 
     85 	VMCMD_EVCNT_INCR(calls);
     86 	KASSERT(proc != vmcmd_map_pagedvn || (vp->v_iflag & VI_TEXT));
     87 	KASSERT(vp == NULL || vp->v_usecount > 0);
     88 
     89 	if (evsp->evs_used >= evsp->evs_cnt)
     90 		vmcmdset_extend(evsp);
     91 	vcp = &evsp->evs_cmds[evsp->evs_used++];
     92 	vcp->ev_proc = proc;
     93 	vcp->ev_len = len;
     94 	vcp->ev_addr = addr;
     95 	if ((vcp->ev_vp = vp) != NULL)
     96 		vref(vp);
     97 	vcp->ev_offset = offset;
     98 	vcp->ev_prot = prot;
     99 	vcp->ev_flags = flags;
    100 }
    101 
    102 void
    103 vmcmdset_extend(struct exec_vmcmd_set *evsp)
    104 {
    105 	struct exec_vmcmd *nvcp;
    106 	u_int ocnt;
    107 
    108 #ifdef DIAGNOSTIC
    109 	if (evsp->evs_used < evsp->evs_cnt)
    110 		panic("vmcmdset_extend: not necessary");
    111 #endif
    112 
    113 	/* figure out number of entries in new set */
    114 	if ((ocnt = evsp->evs_cnt) != 0) {
    115 		evsp->evs_cnt += ocnt;
    116 		VMCMD_EVCNT_INCR(extends);
    117 	} else
    118 		evsp->evs_cnt = EXEC_DEFAULT_VMCMD_SETSIZE;
    119 
    120 	/* allocate it */
    121 	nvcp = kmem_alloc(evsp->evs_cnt * sizeof(struct exec_vmcmd), KM_SLEEP);
    122 
    123 	/* free the old struct, if there was one, and record the new one */
    124 	if (ocnt) {
    125 		memcpy(nvcp, evsp->evs_cmds,
    126 		    (ocnt * sizeof(struct exec_vmcmd)));
    127 		kmem_free(evsp->evs_cmds, ocnt * sizeof(struct exec_vmcmd));
    128 	}
    129 	evsp->evs_cmds = nvcp;
    130 }
    131 
    132 void
    133 kill_vmcmds(struct exec_vmcmd_set *evsp)
    134 {
    135 	struct exec_vmcmd *vcp;
    136 	u_int i;
    137 
    138 	VMCMD_EVCNT_INCR(kills);
    139 
    140 	if (evsp->evs_cnt == 0)
    141 		return;
    142 
    143 	for (i = 0; i < evsp->evs_used; i++) {
    144 		vcp = &evsp->evs_cmds[i];
    145 		if (vcp->ev_vp != NULL)
    146 			vrele(vcp->ev_vp);
    147 	}
    148 	kmem_free(evsp->evs_cmds, evsp->evs_cnt * sizeof(struct exec_vmcmd));
    149 	evsp->evs_used = evsp->evs_cnt = 0;
    150 }
    151 
    152 /*
    153  * vmcmd_map_pagedvn():
    154  *	handle vmcmd which specifies that a vnode should be mmap'd.
    155  *	appropriate for handling demand-paged text and data segments.
    156  */
    157 
    158 static int
    159 vmcmd_get_prot(struct lwp *l, const struct exec_vmcmd *cmd, vm_prot_t *prot,
    160     vm_prot_t *maxprot)
    161 {
    162 
    163 	*prot = cmd->ev_prot;
    164 	*maxprot = PAX_MPROTECT_MAXPROTECT(l, *prot, 0, UVM_PROT_ALL);
    165 
    166 	if ((*prot & *maxprot) != *prot)
    167 		return EACCES;
    168 	return PAX_MPROTECT_VALIDATE(l, *prot);
    169 }
    170 
    171 int
    172 vmcmd_map_pagedvn(struct lwp *l, struct exec_vmcmd *cmd)
    173 {
    174 	struct uvm_object *uobj;
    175 	struct vnode *vp = cmd->ev_vp;
    176 	struct proc *p = l->l_proc;
    177 	int error;
    178 	vm_prot_t prot, maxprot;
    179 
    180 	KASSERT(vp->v_iflag & VI_TEXT);
    181 
    182 	/*
    183 	 * map the vnode in using uvm_map.
    184 	 */
    185 
    186 	if (cmd->ev_len == 0)
    187 		return 0;
    188 	if (cmd->ev_offset & PAGE_MASK)
    189 		return EINVAL;
    190 	if (cmd->ev_addr & PAGE_MASK)
    191 		return EINVAL;
    192 	if (cmd->ev_len & PAGE_MASK)
    193 		return EINVAL;
    194 
    195 	if ((error = vmcmd_get_prot(l, cmd, &prot, &maxprot)) != 0)
    196 		return error;
    197 
    198 	/*
    199 	 * check the file system's opinion about mmapping the file
    200 	 */
    201 
    202 	error = VOP_MMAP(vp, prot, l->l_cred);
    203 	if (error)
    204 		return error;
    205 
    206 	if ((vp->v_vflag & VV_MAPPED) == 0) {
    207 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
    208 		vp->v_vflag |= VV_MAPPED;
    209 		VOP_UNLOCK(vp);
    210 	}
    211 
    212 	/*
    213 	 * do the map, reference the object for this map entry
    214 	 */
    215 	uobj = &vp->v_uobj;
    216 	vref(vp);
    217 
    218 	error = uvm_map(&p->p_vmspace->vm_map, &cmd->ev_addr, cmd->ev_len,
    219 		uobj, cmd->ev_offset, 0,
    220 		UVM_MAPFLAG(prot, maxprot, UVM_INH_COPY,
    221 			UVM_ADV_NORMAL, UVM_FLAG_COPYONW|UVM_FLAG_FIXED));
    222 	if (error) {
    223 		uobj->pgops->pgo_detach(uobj);
    224 	}
    225 	return error;
    226 }
    227 
    228 /*
    229  * vmcmd_map_readvn():
    230  *	handle vmcmd which specifies that a vnode should be read from.
    231  *	appropriate for non-demand-paged text/data segments, i.e. impure
    232  *	objects (a la OMAGIC and NMAGIC).
    233  */
    234 int
    235 vmcmd_map_readvn(struct lwp *l, struct exec_vmcmd *cmd)
    236 {
    237 	struct proc *p = l->l_proc;
    238 	int error;
    239 	long diff;
    240 
    241 	if (cmd->ev_len == 0)
    242 		return 0;
    243 
    244 	diff = cmd->ev_addr - trunc_page(cmd->ev_addr);
    245 	cmd->ev_addr -= diff;			/* required by uvm_map */
    246 	cmd->ev_offset -= diff;
    247 	cmd->ev_len += diff;
    248 
    249 	error = uvm_map(&p->p_vmspace->vm_map, &cmd->ev_addr,
    250 			round_page(cmd->ev_len), NULL, UVM_UNKNOWN_OFFSET, 0,
    251 			UVM_MAPFLAG(UVM_PROT_ALL, UVM_PROT_ALL, UVM_INH_COPY,
    252 			UVM_ADV_NORMAL,
    253 			UVM_FLAG_FIXED|UVM_FLAG_OVERLAY|UVM_FLAG_COPYONW));
    254 
    255 	if (error)
    256 		return error;
    257 
    258 	return vmcmd_readvn(l, cmd);
    259 }
    260 
    261 int
    262 vmcmd_readvn(struct lwp *l, struct exec_vmcmd *cmd)
    263 {
    264 	struct proc *p = l->l_proc;
    265 	int error;
    266 	vm_prot_t prot, maxprot;
    267 
    268 	error = vn_rdwr(UIO_READ, cmd->ev_vp, (void *)cmd->ev_addr,
    269 	    cmd->ev_len, cmd->ev_offset, UIO_USERSPACE, IO_UNIT,
    270 	    l->l_cred, NULL, l);
    271 	if (error)
    272 		return error;
    273 
    274 	if ((error = vmcmd_get_prot(l, cmd, &prot, &maxprot)) != 0)
    275 		return error;
    276 
    277 #ifdef PMAP_NEED_PROCWR
    278 	/*
    279 	 * we had to write the process, make sure the pages are synched
    280 	 * with the instruction cache.
    281 	 */
    282 	if (prot & VM_PROT_EXECUTE)
    283 		pmap_procwr(p, cmd->ev_addr, cmd->ev_len);
    284 #endif
    285 
    286 	/*
    287 	 * we had to map in the area at PROT_ALL so that vn_rdwr()
    288 	 * could write to it.   however, the caller seems to want
    289 	 * it mapped read-only, so now we are going to have to call
    290 	 * uvm_map_protect() to fix up the protection.  ICK.
    291 	 */
    292 	if (maxprot != VM_PROT_ALL) {
    293 		error = uvm_map_protect(&p->p_vmspace->vm_map,
    294 				trunc_page(cmd->ev_addr),
    295 				round_page(cmd->ev_addr + cmd->ev_len),
    296 				maxprot, true);
    297 		if (error)
    298 			return error;
    299 	}
    300 
    301 	if (prot != maxprot) {
    302 		error = uvm_map_protect(&p->p_vmspace->vm_map,
    303 				trunc_page(cmd->ev_addr),
    304 				round_page(cmd->ev_addr + cmd->ev_len),
    305 				prot, false);
    306 		if (error)
    307 			return error;
    308 	}
    309 
    310 	return 0;
    311 }
    312 
    313 /*
    314  * vmcmd_map_zero():
    315  *	handle vmcmd which specifies a zero-filled address space region.  The
    316  *	address range must be first allocated, then protected appropriately.
    317  */
    318 
    319 int
    320 vmcmd_map_zero(struct lwp *l, struct exec_vmcmd *cmd)
    321 {
    322 	struct proc *p = l->l_proc;
    323 	int error;
    324 	long diff;
    325 	vm_prot_t prot, maxprot;
    326 
    327 	diff = cmd->ev_addr - trunc_page(cmd->ev_addr);
    328 	cmd->ev_addr -= diff;			/* required by uvm_map */
    329 	cmd->ev_len += diff;
    330 
    331 	if ((error = vmcmd_get_prot(l, cmd, &prot, &maxprot)) != 0)
    332 		return error;
    333 
    334 	error = uvm_map(&p->p_vmspace->vm_map, &cmd->ev_addr,
    335 			round_page(cmd->ev_len), NULL, UVM_UNKNOWN_OFFSET, 0,
    336 			UVM_MAPFLAG(prot, maxprot, UVM_INH_COPY,
    337 			UVM_ADV_NORMAL,
    338 			UVM_FLAG_FIXED|UVM_FLAG_COPYONW));
    339 	if (cmd->ev_flags & VMCMD_STACK)
    340 		curproc->p_vmspace->vm_issize += atop(round_page(cmd->ev_len));
    341 	return error;
    342 }
    343 
    344 /*
    345  * exec_read_from():
    346  *
    347  *	Read from vnode into buffer at offset.
    348  */
    349 int
    350 exec_read_from(struct lwp *l, struct vnode *vp, u_long off, void *bf,
    351     size_t size)
    352 {
    353 	int error;
    354 	size_t resid;
    355 
    356 	if ((error = vn_rdwr(UIO_READ, vp, bf, size, off, UIO_SYSSPACE,
    357 	    0, l->l_cred, &resid, NULL)) != 0)
    358 		return error;
    359 	/*
    360 	 * See if we got all of it
    361 	 */
    362 	if (resid != 0)
    363 		return ENOEXEC;
    364 	return 0;
    365 }
    366 
    367 /*
    368  * exec_setup_stack(): Set up the stack segment for an elf
    369  * executable.
    370  *
    371  * Note that the ep_ssize parameter must be set to be the current stack
    372  * limit; this is adjusted in the body of execve() to yield the
    373  * appropriate stack segment usage once the argument length is
    374  * calculated.
    375  *
    376  * This function returns an int for uniformity with other (future) formats'
    377  * stack setup functions.  They might have errors to return.
    378  */
    379 
    380 int
    381 exec_setup_stack(struct lwp *l, struct exec_package *epp)
    382 {
    383 	vsize_t max_stack_size;
    384 	vaddr_t access_linear_min;
    385 	vsize_t access_size;
    386 	vaddr_t noaccess_linear_min;
    387 	vsize_t noaccess_size;
    388 
    389 #ifndef	USRSTACK32
    390 #define USRSTACK32	(0x00000000ffffffffL&~PGOFSET)
    391 #endif
    392 #ifndef MAXSSIZ32
    393 #define MAXSSIZ32	(MAXSSIZ >> 2)
    394 #endif
    395 
    396 	if (epp->ep_flags & EXEC_32) {
    397 		epp->ep_minsaddr = USRSTACK32;
    398 		max_stack_size = MAXSSIZ32;
    399 	} else {
    400 		epp->ep_minsaddr = USRSTACK;
    401 		max_stack_size = MAXSSIZ;
    402 	}
    403 
    404 	DPRINTF(("ep_minsaddr=%#jx max_stack_size=%#jx\n",
    405 	    (uintmax_t)epp->ep_minsaddr, (uintmax_t)max_stack_size));
    406 
    407 	pax_aslr_stack(epp, &max_stack_size);
    408 
    409 	DPRINTF(("[RLIMIT_STACK].lim_cur=%#jx max_stack_size=%#jx\n",
    410 	    (uintmax_t)l->l_proc->p_rlimit[RLIMIT_STACK].rlim_cur,
    411 	    (uintmax_t)max_stack_size));
    412 	epp->ep_ssize = MIN(l->l_proc->p_rlimit[RLIMIT_STACK].rlim_cur,
    413 	    max_stack_size);
    414 
    415 	l->l_proc->p_stackbase = epp->ep_minsaddr;
    416 
    417 	epp->ep_maxsaddr = (vaddr_t)STACK_GROW(epp->ep_minsaddr,
    418 	    max_stack_size);
    419 
    420 	DPRINTF(("ep_ssize=%#jx ep_minsaddr=%#jx ep_maxsaddr=%#jx\n",
    421 	    (uintmax_t)epp->ep_ssize, (uintmax_t)epp->ep_minsaddr,
    422 	    (uintmax_t)epp->ep_maxsaddr));
    423 
    424 	/*
    425 	 * set up commands for stack.  note that this takes *two*, one to
    426 	 * map the part of the stack which we can access, and one to map
    427 	 * the part which we can't.
    428 	 *
    429 	 * arguably, it could be made into one, but that would require the
    430 	 * addition of another mapping proc, which is unnecessary
    431 	 */
    432 	access_size = epp->ep_ssize;
    433 	access_linear_min = (vaddr_t)STACK_ALLOC(epp->ep_minsaddr, access_size);
    434 	noaccess_size = max_stack_size - access_size;
    435 	noaccess_linear_min = (vaddr_t)STACK_ALLOC(STACK_GROW(epp->ep_minsaddr,
    436 	    access_size), noaccess_size);
    437 
    438 	DPRINTF(("access_size=%#jx, access_linear_min=%#jx, "
    439 	    "noaccess_size=%#jx, noaccess_linear_min=%#jx\n",
    440 	    (uintmax_t)access_size, (uintmax_t)access_linear_min,
    441 	    (uintmax_t)noaccess_size, (uintmax_t)noaccess_linear_min));
    442 
    443 	if (noaccess_size > 0 && noaccess_size <= MAXSSIZ) {
    444 		NEW_VMCMD2(&epp->ep_vmcmds, vmcmd_map_zero, noaccess_size,
    445 		    noaccess_linear_min, NULL, 0, VM_PROT_NONE, VMCMD_STACK);
    446 	}
    447 	KASSERT(access_size > 0 && access_size <= MAXSSIZ);
    448 	NEW_VMCMD2(&epp->ep_vmcmds, vmcmd_map_zero, access_size,
    449 	    access_linear_min, NULL, 0, VM_PROT_READ | VM_PROT_WRITE,
    450 	    VMCMD_STACK);
    451 
    452 	return 0;
    453 }
    454