Cleanup the ui*() API in preparation for the addition of variant-symlink
[dragonfly.git] / sys / kern / kern_exec.c
CommitLineData
984263bc
MD
1/*
2 * Copyright (c) 1993, David Greenman
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: src/sys/kern/kern_exec.c,v 1.107.2.15 2002/07/30 15:40:46 nectar Exp $
2b69e610 27 * $DragonFly: src/sys/kern/kern_exec.c,v 1.12 2003/09/23 05:03:51 dillon Exp $
984263bc
MD
28 */
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/sysproto.h>
33#include <sys/kernel.h>
34#include <sys/mount.h>
35#include <sys/filedesc.h>
36#include <sys/fcntl.h>
37#include <sys/acct.h>
38#include <sys/exec.h>
39#include <sys/imgact.h>
40#include <sys/imgact_elf.h>
41#include <sys/wait.h>
42#include <sys/malloc.h>
43#include <sys/proc.h>
44#include <sys/signalvar.h>
45#include <sys/pioctl.h>
46#include <sys/namei.h>
47#include <sys/sysent.h>
48#include <sys/shm.h>
49#include <sys/sysctl.h>
50#include <sys/vnode.h>
51#include <sys/aio.h>
52
53#include <vm/vm.h>
54#include <vm/vm_param.h>
55#include <sys/lock.h>
56#include <vm/pmap.h>
57#include <vm/vm_page.h>
58#include <vm/vm_map.h>
59#include <vm/vm_kern.h>
60#include <vm/vm_extern.h>
61#include <vm/vm_object.h>
62#include <vm/vm_pager.h>
63
64#include <sys/user.h>
65#include <machine/reg.h>
66
67MALLOC_DEFINE(M_PARGS, "proc-args", "Process arguments");
68
402ed7e1 69static register_t *exec_copyout_strings (struct image_params *);
984263bc
MD
70
71/* XXX This should be vm_size_t. */
72static u_long ps_strings = PS_STRINGS;
73SYSCTL_ULONG(_kern, KERN_PS_STRINGS, ps_strings, CTLFLAG_RD, &ps_strings, 0, "");
74
75/* XXX This should be vm_size_t. */
76static u_long usrstack = USRSTACK;
77SYSCTL_ULONG(_kern, KERN_USRSTACK, usrstack, CTLFLAG_RD, &usrstack, 0, "");
78
79u_long ps_arg_cache_limit = PAGE_SIZE / 16;
80SYSCTL_LONG(_kern, OID_AUTO, ps_arg_cache_limit, CTLFLAG_RW,
81 &ps_arg_cache_limit, 0, "");
82
83int ps_argsopen = 1;
84SYSCTL_INT(_kern, OID_AUTO, ps_argsopen, CTLFLAG_RW, &ps_argsopen, 0, "");
85
86/*
87 * Each of the items is a pointer to a `const struct execsw', hence the
88 * double pointer here.
89 */
90static const struct execsw **execsw;
91
984263bc
MD
92/*
93 * execve() system call.
94 */
95int
41c20dac 96execve(struct execve_args *uap)
984263bc 97{
dadab5e9
MD
98 struct thread *td = curthread;
99 struct proc *p = td->td_proc;
984263bc
MD
100 struct nameidata nd, *ndp;
101 register_t *stack_base;
102 int error, len, i;
103 struct image_params image_params, *imgp;
104 struct vattr attr;
402ed7e1 105 int (*img_first) (struct image_params *);
984263bc 106
dadab5e9 107 KKASSERT(p);
984263bc
MD
108 imgp = &image_params;
109
110 /*
111 * Lock the process and set the P_INEXEC flag to indicate that
112 * it should be left alone until we're done here. This is
113 * necessary to avoid race conditions - e.g. in ptrace() -
114 * that might allow a local user to illicitly obtain elevated
115 * privileges.
116 */
117 p->p_flag |= P_INEXEC;
118
119 /*
120 * Initialize part of the common data
121 */
122 imgp->proc = p;
123 imgp->uap = uap;
124 imgp->attr = &attr;
125 imgp->argc = imgp->envc = 0;
126 imgp->argv0 = NULL;
127 imgp->entry_addr = 0;
128 imgp->vmspace_destroyed = 0;
129 imgp->interpreted = 0;
130 imgp->interpreter_name[0] = '\0';
131 imgp->auxargs = NULL;
132 imgp->vp = NULL;
133 imgp->firstpage = NULL;
134 imgp->ps_strings = 0;
135
136 /*
137 * Allocate temporary demand zeroed space for argument and
138 * environment strings
139 */
140 imgp->stringbase = (char *)kmem_alloc_wait(exec_map, ARG_MAX + PAGE_SIZE);
141 if (imgp->stringbase == NULL) {
142 error = ENOMEM;
143 goto exec_fail;
144 }
145 imgp->stringp = imgp->stringbase;
146 imgp->stringspace = ARG_MAX;
147 imgp->image_header = imgp->stringbase + ARG_MAX;
148
149 /*
150 * Translate the file name. namei() returns a vnode pointer
151 * in ni_vp amoung other things.
152 */
153 ndp = &nd;
2b69e610 154 NDINIT(ndp, NAMEI_LOOKUP, CNP_LOCKLEAF | CNP_FOLLOW | CNP_SAVENAME,
dadab5e9 155 UIO_USERSPACE, uap->fname, td);
984263bc
MD
156
157interpret:
158
159 error = namei(ndp);
160 if (error) {
161 kmem_free_wakeup(exec_map, (vm_offset_t)imgp->stringbase,
162 ARG_MAX + PAGE_SIZE);
163 goto exec_fail;
164 }
165
166 imgp->vp = ndp->ni_vp;
167 imgp->fname = uap->fname;
168
169 /*
170 * Check file permissions (also 'opens' file)
171 */
172 error = exec_check_permissions(imgp);
173 if (error) {
dadab5e9 174 VOP_UNLOCK(imgp->vp, 0, td);
984263bc
MD
175 goto exec_fail_dealloc;
176 }
177
178 error = exec_map_first_page(imgp);
dadab5e9 179 VOP_UNLOCK(imgp->vp, 0, td);
984263bc
MD
180 if (error)
181 goto exec_fail_dealloc;
182
183 /*
184 * If the current process has a special image activator it
185 * wants to try first, call it. For example, emulating shell
186 * scripts differently.
187 */
188 error = -1;
189 if ((img_first = imgp->proc->p_sysent->sv_imgact_try) != NULL)
190 error = img_first(imgp);
191
192 /*
193 * Loop through the list of image activators, calling each one.
194 * An activator returns -1 if there is no match, 0 on success,
195 * and an error otherwise.
196 */
197 for (i = 0; error == -1 && execsw[i]; ++i) {
198 if (execsw[i]->ex_imgact == NULL ||
199 execsw[i]->ex_imgact == img_first) {
200 continue;
201 }
202 error = (*execsw[i]->ex_imgact)(imgp);
203 }
204
205 if (error) {
206 if (error == -1)
207 error = ENOEXEC;
208 goto exec_fail_dealloc;
209 }
210
211 /*
212 * Special interpreter operation, cleanup and loop up to try to
213 * activate the interpreter.
214 */
215 if (imgp->interpreted) {
216 exec_unmap_first_page(imgp);
217 /* free name buffer and old vnode */
218 NDFREE(ndp, NDF_ONLY_PNBUF);
219 vrele(ndp->ni_vp);
220 /* set new name to that of the interpreter */
2b69e610
MD
221 NDINIT(ndp, NAMEI_LOOKUP,
222 CNP_LOCKLEAF | CNP_FOLLOW | CNP_SAVENAME,
dadab5e9 223 UIO_SYSSPACE, imgp->interpreter_name, td);
984263bc
MD
224 goto interpret;
225 }
226
227 /*
228 * Copy out strings (args and env) and initialize stack base
229 */
230 stack_base = exec_copyout_strings(imgp);
231 p->p_vmspace->vm_minsaddr = (char *)stack_base;
232
233 /*
234 * If custom stack fixup routine present for this process
235 * let it do the stack setup.
236 * Else stuff argument count as first item on stack
237 */
238 if (p->p_sysent->sv_fixup)
239 (*p->p_sysent->sv_fixup)(&stack_base, imgp);
240 else
241 suword(--stack_base, imgp->argc);
242
243 /*
244 * For security and other reasons, the file descriptor table cannot
245 * be shared after an exec.
246 */
247 if (p->p_fd->fd_refcnt > 1) {
248 struct filedesc *tmp;
249
250 tmp = fdcopy(p);
251 fdfree(p);
252 p->p_fd = tmp;
253 }
254
255 /*
256 * For security and other reasons, signal handlers cannot
257 * be shared after an exec. The new proces gets a copy of the old
258 * handlers. In execsigs(), the new process will have its signals
259 * reset.
260 */
261 if (p->p_procsig->ps_refcnt > 1) {
262 struct procsig *newprocsig;
263
264 MALLOC(newprocsig, struct procsig *, sizeof(struct procsig),
265 M_SUBPROC, M_WAITOK);
266 bcopy(p->p_procsig, newprocsig, sizeof(*newprocsig));
267 p->p_procsig->ps_refcnt--;
268 p->p_procsig = newprocsig;
269 p->p_procsig->ps_refcnt = 1;
270 if (p->p_sigacts == &p->p_addr->u_sigacts)
271 panic("shared procsig but private sigacts?");
272
273 p->p_addr->u_sigacts = *p->p_sigacts;
274 p->p_sigacts = &p->p_addr->u_sigacts;
275 }
276
277 /* Stop profiling */
278 stopprofclock(p);
279
280 /* close files on exec */
281 fdcloseexec(p);
282
283 /* reset caught signals */
284 execsigs(p);
285
286 /* name this process - nameiexec(p, ndp) */
287 len = min(ndp->ni_cnd.cn_namelen,MAXCOMLEN);
288 bcopy(ndp->ni_cnd.cn_nameptr, p->p_comm, len);
289 p->p_comm[len] = 0;
290
291 /*
292 * mark as execed, wakeup the process that vforked (if any) and tell
293 * it that it now has its own resources back
294 */
295 p->p_flag |= P_EXEC;
296 if (p->p_pptr && (p->p_flag & P_PPWAIT)) {
297 p->p_flag &= ~P_PPWAIT;
298 wakeup((caddr_t)p->p_pptr);
299 }
300
301 /*
302 * Implement image setuid/setgid.
303 *
304 * Don't honor setuid/setgid if the filesystem prohibits it or if
305 * the process is being traced.
306 */
307 if ((((attr.va_mode & VSUID) && p->p_ucred->cr_uid != attr.va_uid) ||
308 ((attr.va_mode & VSGID) && p->p_ucred->cr_gid != attr.va_gid)) &&
309 (imgp->vp->v_mount->mnt_flag & MNT_NOSUID) == 0 &&
310 (p->p_flag & P_TRACED) == 0) {
311 /*
312 * Turn off syscall tracing for set-id programs, except for
313 * root. Record any set-id flags first to make sure that
314 * we do not regain any tracing during a possible block.
315 */
41c20dac 316 setsugid();
dadab5e9 317 if (p->p_tracep && suser(td)) {
984263bc
MD
318 struct vnode *vtmp;
319
320 if ((vtmp = p->p_tracep) != NULL) {
321 p->p_tracep = NULL;
322 p->p_traceflag = 0;
323 vrele(vtmp);
324 }
325 }
326 /* Close any file descriptors 0..2 that reference procfs */
327 setugidsafety(p);
328 /* Make sure file descriptors 0..2 are in use. */
329 error = fdcheckstd(p);
330 if (error != 0)
331 goto exec_fail_dealloc;
332 /*
333 * Set the new credentials.
334 */
e9a372eb 335 cratom(&p->p_ucred);
984263bc 336 if (attr.va_mode & VSUID)
41c20dac 337 change_euid(attr.va_uid);
984263bc
MD
338 if (attr.va_mode & VSGID)
339 p->p_ucred->cr_gid = attr.va_gid;
340 } else {
41c20dac
MD
341 if (p->p_ucred->cr_uid == p->p_ucred->cr_ruid &&
342 p->p_ucred->cr_gid == p->p_ucred->cr_rgid)
984263bc
MD
343 p->p_flag &= ~P_SUGID;
344 }
345
346 /*
347 * Implement correct POSIX saved-id behavior.
348 */
115ccd83
MD
349 if (p->p_ucred->cr_svuid != p->p_ucred->cr_uid ||
350 p->p_ucred->cr_svgid != p->p_ucred->cr_gid) {
351 cratom(&p->p_ucred);
352 p->p_ucred->cr_svuid = p->p_ucred->cr_uid;
353 p->p_ucred->cr_svgid = p->p_ucred->cr_gid;
354 }
984263bc
MD
355
356 /*
357 * Store the vp for use in procfs
358 */
359 if (p->p_textvp) /* release old reference */
360 vrele(p->p_textvp);
361 VREF(ndp->ni_vp);
362 p->p_textvp = ndp->ni_vp;
363
364 /*
365 * Notify others that we exec'd, and clear the P_INEXEC flag
366 * as we're now a bona fide freshly-execed process.
367 */
368 KNOTE(&p->p_klist, NOTE_EXEC);
369 p->p_flag &= ~P_INEXEC;
370
371 /*
372 * If tracing the process, trap to debugger so breakpoints
373 * can be set before the program executes.
374 */
375 STOPEVENT(p, S_EXEC, 0);
376
377 if (p->p_flag & P_TRACED)
378 psignal(p, SIGTRAP);
379
380 /* clear "fork but no exec" flag, as we _are_ execing */
381 p->p_acflag &= ~AFORK;
382
383 /* Set values passed into the program in registers. */
384 setregs(p, imgp->entry_addr, (u_long)(uintptr_t)stack_base,
385 imgp->ps_strings);
386
c0510e9a
MD
387 /*
388 * The syscall result is returned in registers to the new program.
389 * Linux will register %edx as an atexit function and we must be
390 * sure to set it to 0. XXX
391 */
392 uap->sysmsg_result64 = 0;
393
984263bc
MD
394 /* Free any previous argument cache */
395 if (p->p_args && --p->p_args->ar_ref == 0)
396 FREE(p->p_args, M_PARGS);
397 p->p_args = NULL;
398
399 /* Cache arguments if they fit inside our allowance */
400 i = imgp->endargs - imgp->stringbase;
401 if (ps_arg_cache_limit >= i + sizeof(struct pargs)) {
402 MALLOC(p->p_args, struct pargs *, sizeof(struct pargs) + i,
403 M_PARGS, M_WAITOK);
404 p->p_args->ar_ref = 1;
405 p->p_args->ar_length = i;
406 bcopy(imgp->stringbase, p->p_args->ar_args, i);
407 }
408
409exec_fail_dealloc:
410
411 /*
412 * free various allocated resources
413 */
414 if (imgp->firstpage)
415 exec_unmap_first_page(imgp);
416
417 if (imgp->stringbase != NULL)
418 kmem_free_wakeup(exec_map, (vm_offset_t)imgp->stringbase,
419 ARG_MAX + PAGE_SIZE);
420
421 if (imgp->vp) {
422 NDFREE(ndp, NDF_ONLY_PNBUF);
423 vrele(imgp->vp);
424 }
425
426 if (error == 0)
427 return (0);
428
429exec_fail:
430 /* we're done here, clear P_INEXEC */
431 p->p_flag &= ~P_INEXEC;
432 if (imgp->vmspace_destroyed) {
433 /* sorry, no more process anymore. exit gracefully */
41c20dac 434 exit1(W_EXITCODE(0, SIGABRT));
984263bc
MD
435 /* NOT REACHED */
436 return(0);
437 } else {
438 return(error);
439 }
440}
441
442int
41c20dac 443exec_map_first_page(struct image_params *imgp)
984263bc
MD
444{
445 int s, rv, i;
446 int initial_pagein;
447 vm_page_t ma[VM_INITIAL_PAGEIN];
448 vm_object_t object;
449
450
451 if (imgp->firstpage) {
452 exec_unmap_first_page(imgp);
453 }
454
455 VOP_GETVOBJECT(imgp->vp, &object);
456 s = splvm();
457
458 ma[0] = vm_page_grab(object, 0, VM_ALLOC_NORMAL | VM_ALLOC_RETRY);
459
460 if ((ma[0]->valid & VM_PAGE_BITS_ALL) != VM_PAGE_BITS_ALL) {
461 initial_pagein = VM_INITIAL_PAGEIN;
462 if (initial_pagein > object->size)
463 initial_pagein = object->size;
464 for (i = 1; i < initial_pagein; i++) {
465 if ((ma[i] = vm_page_lookup(object, i)) != NULL) {
466 if ((ma[i]->flags & PG_BUSY) || ma[i]->busy)
467 break;
468 if (ma[i]->valid)
469 break;
470 vm_page_busy(ma[i]);
471 } else {
472 ma[i] = vm_page_alloc(object, i, VM_ALLOC_NORMAL);
473 if (ma[i] == NULL)
474 break;
475 }
476 }
477 initial_pagein = i;
478
479 rv = vm_pager_get_pages(object, ma, initial_pagein, 0);
480 ma[0] = vm_page_lookup(object, 0);
481
482 if ((rv != VM_PAGER_OK) || (ma[0] == NULL) || (ma[0]->valid == 0)) {
483 if (ma[0]) {
484 vm_page_protect(ma[0], VM_PROT_NONE);
485 vm_page_free(ma[0]);
486 }
487 splx(s);
488 return EIO;
489 }
490 }
491
492 vm_page_wire(ma[0]);
493 vm_page_wakeup(ma[0]);
494 splx(s);
495
496 pmap_kenter((vm_offset_t) imgp->image_header, VM_PAGE_TO_PHYS(ma[0]));
497 imgp->firstpage = ma[0];
498
499 return 0;
500}
501
502void
503exec_unmap_first_page(imgp)
504 struct image_params *imgp;
505{
506 if (imgp->firstpage) {
507 pmap_kremove((vm_offset_t) imgp->image_header);
508 vm_page_unwire(imgp->firstpage, 1);
509 imgp->firstpage = NULL;
510 }
511}
512
513/*
514 * Destroy old address space, and allocate a new stack
515 * The new stack is only SGROWSIZ large because it is grown
516 * automatically in trap.c.
517 */
518int
519exec_new_vmspace(imgp)
520 struct image_params *imgp;
521{
522 int error;
523 struct vmspace *vmspace = imgp->proc->p_vmspace;
524 vm_offset_t stack_addr = USRSTACK - maxssiz;
525 vm_map_t map = &vmspace->vm_map;
526
527 imgp->vmspace_destroyed = 1;
528
529 /*
530 * Prevent a pending AIO from modifying the new address space.
531 */
532 aio_proc_rundown(imgp->proc);
533
534 /*
535 * Blow away entire process VM, if address space not shared,
536 * otherwise, create a new VM space so that other threads are
537 * not disrupted
538 */
539 if (vmspace->vm_refcnt == 1) {
fef0fdf2 540 shmexit(vmspace);
984263bc
MD
541 pmap_remove_pages(vmspace_pmap(vmspace), 0, VM_MAXUSER_ADDRESS);
542 vm_map_remove(map, 0, VM_MAXUSER_ADDRESS);
543 } else {
544 vmspace_exec(imgp->proc);
545 vmspace = imgp->proc->p_vmspace;
546 map = &vmspace->vm_map;
547 }
548
549 /* Allocate a new stack */
550 error = vm_map_stack(&vmspace->vm_map, stack_addr, (vm_size_t)maxssiz,
551 VM_PROT_ALL, VM_PROT_ALL, 0);
552 if (error)
553 return (error);
554
555 /* vm_ssize and vm_maxsaddr are somewhat antiquated concepts in the
556 * VM_STACK case, but they are still used to monitor the size of the
557 * process stack so we can check the stack rlimit.
558 */
559 vmspace->vm_ssize = sgrowsiz >> PAGE_SHIFT;
560 vmspace->vm_maxsaddr = (char *)USRSTACK - maxssiz;
561
562 return(0);
563}
564
565/*
566 * Copy out argument and environment strings from the old process
567 * address space into the temporary string buffer.
568 */
569int
570exec_extract_strings(imgp)
571 struct image_params *imgp;
572{
573 char **argv, **envv;
574 char *argp, *envp;
575 int error;
576 size_t length;
577
578 /*
579 * extract arguments first
580 */
581
582 argv = imgp->uap->argv;
583
584 if (argv) {
585 argp = (caddr_t) (intptr_t) fuword(argv);
586 if (argp == (caddr_t) -1)
587 return (EFAULT);
588 if (argp)
589 argv++;
590 if (imgp->argv0)
591 argp = imgp->argv0;
592 if (argp) {
593 do {
594 if (argp == (caddr_t) -1)
595 return (EFAULT);
596 if ((error = copyinstr(argp, imgp->stringp,
597 imgp->stringspace, &length))) {
598 if (error == ENAMETOOLONG)
599 return(E2BIG);
600 return (error);
601 }
602 imgp->stringspace -= length;
603 imgp->stringp += length;
604 imgp->argc++;
605 } while ((argp = (caddr_t) (intptr_t) fuword(argv++)));
606 }
607 }
608
609 imgp->endargs = imgp->stringp;
610
611 /*
612 * extract environment strings
613 */
614
615 envv = imgp->uap->envv;
616
617 if (envv) {
618 while ((envp = (caddr_t) (intptr_t) fuword(envv++))) {
619 if (envp == (caddr_t) -1)
620 return (EFAULT);
621 if ((error = copyinstr(envp, imgp->stringp,
622 imgp->stringspace, &length))) {
623 if (error == ENAMETOOLONG)
624 return(E2BIG);
625 return (error);
626 }
627 imgp->stringspace -= length;
628 imgp->stringp += length;
629 imgp->envc++;
630 }
631 }
632
633 return (0);
634}
635
636/*
637 * Copy strings out to the new process address space, constructing
638 * new arg and env vector tables. Return a pointer to the base
639 * so that it can be used as the initial stack pointer.
640 */
641register_t *
642exec_copyout_strings(imgp)
643 struct image_params *imgp;
644{
645 int argc, envc;
646 char **vectp;
647 char *stringp, *destp;
648 register_t *stack_base;
649 struct ps_strings *arginfo;
650 int szsigcode;
651
652 /*
653 * Calculate string base and vector table pointers.
654 * Also deal with signal trampoline code for this exec type.
655 */
656 arginfo = (struct ps_strings *)PS_STRINGS;
657 szsigcode = *(imgp->proc->p_sysent->sv_szsigcode);
658 destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE -
659 roundup((ARG_MAX - imgp->stringspace), sizeof(char *));
660
661 /*
662 * install sigcode
663 */
664 if (szsigcode)
665 copyout(imgp->proc->p_sysent->sv_sigcode,
666 ((caddr_t)arginfo - szsigcode), szsigcode);
667
668 /*
669 * If we have a valid auxargs ptr, prepare some room
670 * on the stack.
671 */
672 if (imgp->auxargs)
673 /*
674 * The '+ 2' is for the null pointers at the end of each of the
675 * arg and env vector sets, and 'AT_COUNT*2' is room for the
676 * ELF Auxargs data.
677 */
678 vectp = (char **)(destp - (imgp->argc + imgp->envc + 2 +
679 AT_COUNT*2) * sizeof(char*));
680 else
681 /*
682 * The '+ 2' is for the null pointers at the end of each of the
683 * arg and env vector sets
684 */
685 vectp = (char **)
686 (destp - (imgp->argc + imgp->envc + 2) * sizeof(char*));
687
688 /*
689 * vectp also becomes our initial stack base
690 */
691 stack_base = (register_t *)vectp;
692
693 stringp = imgp->stringbase;
694 argc = imgp->argc;
695 envc = imgp->envc;
696
697 /*
698 * Copy out strings - arguments and environment.
699 */
700 copyout(stringp, destp, ARG_MAX - imgp->stringspace);
701
702 /*
703 * Fill in "ps_strings" struct for ps, w, etc.
704 */
705 suword(&arginfo->ps_argvstr, (long)(intptr_t)vectp);
706 suword(&arginfo->ps_nargvstr, argc);
707
708 /*
709 * Fill in argument portion of vector table.
710 */
711 for (; argc > 0; --argc) {
712 suword(vectp++, (long)(intptr_t)destp);
713 while (*stringp++ != 0)
714 destp++;
715 destp++;
716 }
717
718 /* a null vector table pointer seperates the argp's from the envp's */
719 suword(vectp++, 0);
720
721 suword(&arginfo->ps_envstr, (long)(intptr_t)vectp);
722 suword(&arginfo->ps_nenvstr, envc);
723
724 /*
725 * Fill in environment portion of vector table.
726 */
727 for (; envc > 0; --envc) {
728 suword(vectp++, (long)(intptr_t)destp);
729 while (*stringp++ != 0)
730 destp++;
731 destp++;
732 }
733
734 /* end of vector table is a null pointer */
735 suword(vectp, 0);
736
737 return (stack_base);
738}
739
740/*
741 * Check permissions of file to execute.
742 * Return 0 for success or error code on failure.
743 */
744int
745exec_check_permissions(imgp)
746 struct image_params *imgp;
747{
748 struct proc *p = imgp->proc;
749 struct vnode *vp = imgp->vp;
750 struct vattr *attr = imgp->attr;
dadab5e9 751 struct thread *td = p->p_thread;
984263bc
MD
752 int error;
753
754 /* Get file attributes */
3b568787 755 error = VOP_GETATTR(vp, attr, td);
984263bc
MD
756 if (error)
757 return (error);
758
759 /*
760 * 1) Check if file execution is disabled for the filesystem that this
761 * file resides on.
762 * 2) Insure that at least one execute bit is on - otherwise root
763 * will always succeed, and we don't want to happen unless the
764 * file really is executable.
765 * 3) Insure that the file is a regular file.
766 */
767 if ((vp->v_mount->mnt_flag & MNT_NOEXEC) ||
768 ((attr->va_mode & 0111) == 0) ||
769 (attr->va_type != VREG)) {
770 return (EACCES);
771 }
772
773 /*
774 * Zero length files can't be exec'd
775 */
776 if (attr->va_size == 0)
777 return (ENOEXEC);
778
779 /*
780 * Check for execute permission to file based on current credentials.
781 */
dadab5e9 782 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, td);
984263bc
MD
783 if (error)
784 return (error);
785
786 /*
787 * Check number of open-for-writes on the file and deny execution
788 * if there are any.
789 */
790 if (vp->v_writecount)
791 return (ETXTBSY);
792
793 /*
794 * Call filesystem specific open routine (which does nothing in the
795 * general case).
796 */
dadab5e9 797 error = VOP_OPEN(vp, FREAD, p->p_ucred, td);
984263bc
MD
798 if (error)
799 return (error);
800
801 return (0);
802}
803
804/*
805 * Exec handler registration
806 */
807int
808exec_register(execsw_arg)
809 const struct execsw *execsw_arg;
810{
811 const struct execsw **es, **xs, **newexecsw;
812 int count = 2; /* New slot and trailing NULL */
813
814 if (execsw)
815 for (es = execsw; *es; es++)
816 count++;
817 newexecsw = malloc(count * sizeof(*es), M_TEMP, M_WAITOK);
818 if (newexecsw == NULL)
819 return ENOMEM;
820 xs = newexecsw;
821 if (execsw)
822 for (es = execsw; *es; es++)
823 *xs++ = *es;
824 *xs++ = execsw_arg;
825 *xs = NULL;
826 if (execsw)
827 free(execsw, M_TEMP);
828 execsw = newexecsw;
829 return 0;
830}
831
832int
833exec_unregister(execsw_arg)
834 const struct execsw *execsw_arg;
835{
836 const struct execsw **es, **xs, **newexecsw;
837 int count = 1;
838
839 if (execsw == NULL)
840 panic("unregister with no handlers left?\n");
841
842 for (es = execsw; *es; es++) {
843 if (*es == execsw_arg)
844 break;
845 }
846 if (*es == NULL)
847 return ENOENT;
848 for (es = execsw; *es; es++)
849 if (*es != execsw_arg)
850 count++;
851 newexecsw = malloc(count * sizeof(*es), M_TEMP, M_WAITOK);
852 if (newexecsw == NULL)
853 return ENOMEM;
854 xs = newexecsw;
855 for (es = execsw; *es; es++)
856 if (*es != execsw_arg)
857 *xs++ = *es;
858 *xs = NULL;
859 if (execsw)
860 free(execsw, M_TEMP);
861 execsw = newexecsw;
862 return 0;
863}