1 /* $NetBSD: exec_subr.c,v 1.62 2009/03/29 01:02:50 mrg Exp $ */
4 * Copyright (c) 1993, 1994, 1996 Christopher G. Demetriou
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: exec_subr.c,v 1.62 2009/03/29 01:02:50 mrg Exp $");
38 #include <sys/param.h>
39 #include <sys/systm.h>
42 #include <sys/vnode.h>
43 #include <sys/filedesc.h>
46 #include <sys/resourcevar.h>
47 #include <sys/device.h>
51 #endif /* PAX_MPROTECT */
55 #define VMCMD_EVCNT_DECL(name) \
56 static struct evcnt vmcmd_ev_##name = \
57 EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "vmcmd", #name); \
58 EVCNT_ATTACH_STATIC(vmcmd_ev_##name)
60 #define VMCMD_EVCNT_INCR(name) \
61 vmcmd_ev_##name.ev_count++
63 VMCMD_EVCNT_DECL(calls
);
64 VMCMD_EVCNT_DECL(extends
);
65 VMCMD_EVCNT_DECL(kills
);
69 * create a new vmcmd structure and fill in its fields based
70 * on function call arguments. make sure objects ref'd by
71 * the vmcmd are 'held'.
75 new_vmcmd(struct exec_vmcmd_set
*evsp
,
76 int (*proc
)(struct lwp
* l
, struct exec_vmcmd
*),
77 vsize_t len
, vaddr_t addr
, struct vnode
*vp
, u_long offset
,
78 u_int prot
, int flags
)
80 struct exec_vmcmd
*vcp
;
82 VMCMD_EVCNT_INCR(calls
);
84 if (evsp
->evs_used
>= evsp
->evs_cnt
)
85 vmcmdset_extend(evsp
);
86 vcp
= &evsp
->evs_cmds
[evsp
->evs_used
++];
90 if ((vcp
->ev_vp
= vp
) != NULL
)
92 vcp
->ev_offset
= offset
;
94 vcp
->ev_flags
= flags
;
98 vmcmdset_extend(struct exec_vmcmd_set
*evsp
)
100 struct exec_vmcmd
*nvcp
;
104 if (evsp
->evs_used
< evsp
->evs_cnt
)
105 panic("vmcmdset_extend: not necessary");
108 /* figure out number of entries in new set */
109 if ((ocnt
= evsp
->evs_cnt
) != 0) {
110 evsp
->evs_cnt
+= ocnt
;
111 VMCMD_EVCNT_INCR(extends
);
113 evsp
->evs_cnt
= EXEC_DEFAULT_VMCMD_SETSIZE
;
116 nvcp
= kmem_alloc(evsp
->evs_cnt
* sizeof(struct exec_vmcmd
), KM_SLEEP
);
118 /* free the old struct, if there was one, and record the new one */
120 memcpy(nvcp
, evsp
->evs_cmds
,
121 (ocnt
* sizeof(struct exec_vmcmd
)));
122 kmem_free(evsp
->evs_cmds
, ocnt
* sizeof(struct exec_vmcmd
));
124 evsp
->evs_cmds
= nvcp
;
128 kill_vmcmds(struct exec_vmcmd_set
*evsp
)
130 struct exec_vmcmd
*vcp
;
133 VMCMD_EVCNT_INCR(kills
);
135 if (evsp
->evs_cnt
== 0)
138 for (i
= 0; i
< evsp
->evs_used
; i
++) {
139 vcp
= &evsp
->evs_cmds
[i
];
140 if (vcp
->ev_vp
!= NULL
)
143 kmem_free(evsp
->evs_cmds
, evsp
->evs_cnt
* sizeof(struct exec_vmcmd
));
144 evsp
->evs_used
= evsp
->evs_cnt
= 0;
148 * vmcmd_map_pagedvn():
149 * handle vmcmd which specifies that a vnode should be mmap'd.
150 * appropriate for handling demand-paged text and data segments.
154 vmcmd_map_pagedvn(struct lwp
*l
, struct exec_vmcmd
*cmd
)
156 struct uvm_object
*uobj
;
157 struct vnode
*vp
= cmd
->ev_vp
;
158 struct proc
*p
= l
->l_proc
;
160 vm_prot_t prot
, maxprot
;
162 KASSERT(vp
->v_iflag
& VI_TEXT
);
165 * map the vnode in using uvm_map.
168 if (cmd
->ev_len
== 0)
170 if (cmd
->ev_offset
& PAGE_MASK
)
172 if (cmd
->ev_addr
& PAGE_MASK
)
174 if (cmd
->ev_len
& PAGE_MASK
)
178 maxprot
= UVM_PROT_ALL
;
180 pax_mprotect(l
, &prot
, &maxprot
);
181 #endif /* PAX_MPROTECT */
184 * check the file system's opinion about mmapping the file
187 error
= VOP_MMAP(vp
, prot
, l
->l_cred
);
191 if ((vp
->v_vflag
& VV_MAPPED
) == 0) {
192 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
);
193 vp
->v_vflag
|= VV_MAPPED
;
198 * do the map, reference the object for this map entry
203 error
= uvm_map(&p
->p_vmspace
->vm_map
, &cmd
->ev_addr
, cmd
->ev_len
,
204 uobj
, cmd
->ev_offset
, 0,
205 UVM_MAPFLAG(prot
, maxprot
, UVM_INH_COPY
,
206 UVM_ADV_NORMAL
, UVM_FLAG_COPYONW
|UVM_FLAG_FIXED
));
208 uobj
->pgops
->pgo_detach(uobj
);
214 * vmcmd_map_readvn():
215 * handle vmcmd which specifies that a vnode should be read from.
216 * appropriate for non-demand-paged text/data segments, i.e. impure
217 * objects (a la OMAGIC and NMAGIC).
220 vmcmd_map_readvn(struct lwp
*l
, struct exec_vmcmd
*cmd
)
222 struct proc
*p
= l
->l_proc
;
226 if (cmd
->ev_len
== 0)
229 diff
= cmd
->ev_addr
- trunc_page(cmd
->ev_addr
);
230 cmd
->ev_addr
-= diff
; /* required by uvm_map */
231 cmd
->ev_offset
-= diff
;
234 error
= uvm_map(&p
->p_vmspace
->vm_map
, &cmd
->ev_addr
,
235 round_page(cmd
->ev_len
), NULL
, UVM_UNKNOWN_OFFSET
, 0,
236 UVM_MAPFLAG(UVM_PROT_ALL
, UVM_PROT_ALL
, UVM_INH_COPY
,
238 UVM_FLAG_FIXED
|UVM_FLAG_OVERLAY
|UVM_FLAG_COPYONW
));
243 return vmcmd_readvn(l
, cmd
);
247 vmcmd_readvn(struct lwp
*l
, struct exec_vmcmd
*cmd
)
249 struct proc
*p
= l
->l_proc
;
251 vm_prot_t prot
, maxprot
;
253 error
= vn_rdwr(UIO_READ
, cmd
->ev_vp
, (void *)cmd
->ev_addr
,
254 cmd
->ev_len
, cmd
->ev_offset
, UIO_USERSPACE
, IO_UNIT
,
260 maxprot
= VM_PROT_ALL
;
262 pax_mprotect(l
, &prot
, &maxprot
);
263 #endif /* PAX_MPROTECT */
265 #ifdef PMAP_NEED_PROCWR
267 * we had to write the process, make sure the pages are synched
268 * with the instruction cache.
270 if (prot
& VM_PROT_EXECUTE
)
271 pmap_procwr(p
, cmd
->ev_addr
, cmd
->ev_len
);
275 * we had to map in the area at PROT_ALL so that vn_rdwr()
276 * could write to it. however, the caller seems to want
277 * it mapped read-only, so now we are going to have to call
278 * uvm_map_protect() to fix up the protection. ICK.
280 if (maxprot
!= VM_PROT_ALL
) {
281 error
= uvm_map_protect(&p
->p_vmspace
->vm_map
,
282 trunc_page(cmd
->ev_addr
),
283 round_page(cmd
->ev_addr
+ cmd
->ev_len
),
289 if (prot
!= maxprot
) {
290 error
= uvm_map_protect(&p
->p_vmspace
->vm_map
,
291 trunc_page(cmd
->ev_addr
),
292 round_page(cmd
->ev_addr
+ cmd
->ev_len
),
303 * handle vmcmd which specifies a zero-filled address space region. The
304 * address range must be first allocated, then protected appropriately.
308 vmcmd_map_zero(struct lwp
*l
, struct exec_vmcmd
*cmd
)
310 struct proc
*p
= l
->l_proc
;
313 vm_prot_t prot
, maxprot
;
315 diff
= cmd
->ev_addr
- trunc_page(cmd
->ev_addr
);
316 cmd
->ev_addr
-= diff
; /* required by uvm_map */
320 maxprot
= UVM_PROT_ALL
;
322 pax_mprotect(l
, &prot
, &maxprot
);
323 #endif /* PAX_MPROTECT */
325 error
= uvm_map(&p
->p_vmspace
->vm_map
, &cmd
->ev_addr
,
326 round_page(cmd
->ev_len
), NULL
, UVM_UNKNOWN_OFFSET
, 0,
327 UVM_MAPFLAG(prot
, maxprot
, UVM_INH_COPY
,
329 UVM_FLAG_FIXED
|UVM_FLAG_COPYONW
));
330 if (cmd
->ev_flags
& VMCMD_STACK
)
331 curproc
->p_vmspace
->vm_issize
+= atop(round_page(cmd
->ev_len
));
338 * Read from vnode into buffer at offset.
341 exec_read_from(struct lwp
*l
, struct vnode
*vp
, u_long off
, void *bf
,
347 if ((error
= vn_rdwr(UIO_READ
, vp
, bf
, size
, off
, UIO_SYSSPACE
,
348 0, l
->l_cred
, &resid
, NULL
)) != 0)
351 * See if we got all of it
359 * exec_setup_stack(): Set up the stack segment for an elf
362 * Note that the ep_ssize parameter must be set to be the current stack
363 * limit; this is adjusted in the body of execve() to yield the
364 * appropriate stack segment usage once the argument length is
367 * This function returns an int for uniformity with other (future) formats'
368 * stack setup functions. They might have errors to return.
372 exec_setup_stack(struct lwp
*l
, struct exec_package
*epp
)
374 vsize_t max_stack_size
;
375 vaddr_t access_linear_min
;
377 vaddr_t noaccess_linear_min
;
378 vsize_t noaccess_size
;
381 #define USRSTACK32 (0x00000000ffffffffL&~PGOFSET)
384 if (epp
->ep_flags
& EXEC_32
) {
385 epp
->ep_minsaddr
= USRSTACK32
;
386 max_stack_size
= MAXSSIZ
;
388 epp
->ep_minsaddr
= USRSTACK
;
389 max_stack_size
= MAXSSIZ
;
393 pax_aslr_stack(l
, epp
, &max_stack_size
);
394 #endif /* PAX_ASLR */
396 l
->l_proc
->p_stackbase
= epp
->ep_minsaddr
;
398 epp
->ep_maxsaddr
= (vaddr_t
)STACK_GROW(epp
->ep_minsaddr
,
400 epp
->ep_ssize
= l
->l_proc
->p_rlimit
[RLIMIT_STACK
].rlim_cur
;
403 * set up commands for stack. note that this takes *two*, one to
404 * map the part of the stack which we can access, and one to map
405 * the part which we can't.
407 * arguably, it could be made into one, but that would require the
408 * addition of another mapping proc, which is unnecessary
410 access_size
= epp
->ep_ssize
;
411 access_linear_min
= (vaddr_t
)STACK_ALLOC(epp
->ep_minsaddr
, access_size
);
412 noaccess_size
= max_stack_size
- access_size
;
413 noaccess_linear_min
= (vaddr_t
)STACK_ALLOC(STACK_GROW(epp
->ep_minsaddr
,
414 access_size
), noaccess_size
);
415 if (noaccess_size
> 0) {
416 NEW_VMCMD2(&epp
->ep_vmcmds
, vmcmd_map_zero
, noaccess_size
,
417 noaccess_linear_min
, NULL
, 0, VM_PROT_NONE
, VMCMD_STACK
);
419 KASSERT(access_size
> 0);
420 NEW_VMCMD2(&epp
->ep_vmcmds
, vmcmd_map_zero
, access_size
,
421 access_linear_min
, NULL
, 0, VM_PROT_READ
| VM_PROT_WRITE
,