Deleted Added
full compact
kern_exec.c (12679) kern_exec.c (12819)
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 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by David Greenman
16 * 4. The name of the developer may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
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 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by David Greenman
16 * 4. The name of the developer may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 * $Id: kern_exec.c,v 1.28 1995/12/07 12:46:40 davidg Exp $
31 * $Id: kern_exec.c,v 1.29 1995/12/09 04:29:11 peter Exp $
32 */
33
34#include <sys/param.h>
35#include <sys/systm.h>
36#include <sys/sysproto.h>
37#include <sys/signalvar.h>
38#include <sys/kernel.h>
39#include <sys/mount.h>
40#include <sys/filedesc.h>
41#include <sys/fcntl.h>
42#include <sys/acct.h>
43#include <sys/exec.h>
44#include <sys/imgact.h>
45#include <sys/wait.h>
46#include <sys/malloc.h>
47#include <sys/sysent.h>
48#include <sys/syslog.h>
49#include <sys/shm.h>
50
51#include <vm/vm.h>
52#include <vm/vm_param.h>
53#include <vm/vm_prot.h>
54#include <vm/lock.h>
55#include <vm/pmap.h>
56#include <vm/vm_map.h>
57#include <vm/vm_kern.h>
58#include <vm/vm_extern.h>
59
60#include <machine/reg.h>
61
32 */
33
34#include <sys/param.h>
35#include <sys/systm.h>
36#include <sys/sysproto.h>
37#include <sys/signalvar.h>
38#include <sys/kernel.h>
39#include <sys/mount.h>
40#include <sys/filedesc.h>
41#include <sys/fcntl.h>
42#include <sys/acct.h>
43#include <sys/exec.h>
44#include <sys/imgact.h>
45#include <sys/wait.h>
46#include <sys/malloc.h>
47#include <sys/sysent.h>
48#include <sys/syslog.h>
49#include <sys/shm.h>
50
51#include <vm/vm.h>
52#include <vm/vm_param.h>
53#include <vm/vm_prot.h>
54#include <vm/lock.h>
55#include <vm/pmap.h>
56#include <vm/vm_map.h>
57#include <vm/vm_kern.h>
58#include <vm/vm_extern.h>
59
60#include <machine/reg.h>
61
62int *exec_copyout_strings __P((struct image_params *));
62static int *exec_copyout_strings __P((struct image_params *));
63
64static int exec_check_permissions(struct image_params *);
65
66/*
67 * execsw_set is constructed for us by the linker. Each of the items
68 * is a pointer to a `const struct execsw', hence the double pointer here.
69 */
63
64static int exec_check_permissions(struct image_params *);
65
66/*
67 * execsw_set is constructed for us by the linker. Each of the items
68 * is a pointer to a `const struct execsw', hence the double pointer here.
69 */
70const struct execsw **execsw = (const struct execsw **)&execsw_set.ls_items[0];
70static const struct execsw **execsw =
71 (const struct execsw **)&execsw_set.ls_items[0];
71
72#ifndef _SYS_SYSPROTO_H_
73struct execve_args {
74 char *fname;
75 char **argv;
76 char **envv;
77};
78#endif
79
80/*
81 * execve() system call.
82 */
83int
84execve(p, uap, retval)
85 struct proc *p;
86 register struct execve_args *uap;
87 int *retval;
88{
89 struct nameidata nd, *ndp;
90 int *stack_base;
91 int error, len, i;
92 struct image_params image_params, *imgp;
93 struct vattr attr;
94
95 imgp = &image_params;
96
97 /*
98 * Initialize part of the common data
99 */
100 imgp->proc = p;
101 imgp->uap = uap;
102 imgp->attr = &attr;
103 imgp->image_header = NULL;
104 imgp->argc = imgp->envc = 0;
105 imgp->entry_addr = 0;
106 imgp->vmspace_destroyed = 0;
107 imgp->interpreted = 0;
108 imgp->interpreter_name[0] = '\0';
109
110 /*
111 * Allocate temporary demand zeroed space for argument and
112 * environment strings
113 */
114 imgp->stringbase = (char *)kmem_alloc_pageable(exec_map, ARG_MAX);
115 if (imgp->stringbase == NULL) {
116 error = ENOMEM;
117 goto exec_fail;
118 }
119 imgp->stringp = imgp->stringbase;
120 imgp->stringspace = ARG_MAX;
121
122 /*
123 * Translate the file name. namei() returns a vnode pointer
124 * in ni_vp amoung other things.
125 */
126 ndp = &nd;
127 NDINIT(ndp, LOOKUP, LOCKLEAF | FOLLOW | SAVENAME,
128 UIO_USERSPACE, uap->fname, p);
129
130interpret:
131
132 error = namei(ndp);
133 if (error) {
134 kmem_free(exec_map, (vm_offset_t)imgp->stringbase, ARG_MAX);
135 goto exec_fail;
136 }
137
138 imgp->vp = ndp->ni_vp;
139 if (imgp->vp == NULL) {
140 error = ENOEXEC;
141 goto exec_fail_dealloc;
142 }
143
144 /*
145 * Check file permissions (also 'opens' file)
146 */
147 error = exec_check_permissions(imgp);
148
149 /*
150 * Lose the lock on the vnode. It's no longer needed, and must not
151 * exist for the pagefault paging to work below.
152 */
153 VOP_UNLOCK(imgp->vp);
154
155 if (error)
156 goto exec_fail_dealloc;
157
158 /*
159 * Map the image header (first page) of the file into
160 * kernel address space
161 */
162 error = vm_mmap(kernel_map, /* map */
163 (vm_offset_t *)&imgp->image_header, /* address */
164 PAGE_SIZE, /* size */
165 VM_PROT_READ, /* protection */
166 VM_PROT_READ, /* max protection */
167 0, /* flags */
168 (caddr_t)imgp->vp, /* vnode */
169 0); /* offset */
170 if (error) {
171 uprintf("mmap failed: %d\n",error);
172 goto exec_fail_dealloc;
173 }
174
175 /*
176 * Loop through list of image activators, calling each one.
177 * If there is no match, the activator returns -1. If there
178 * is a match, but there was an error during the activation,
179 * the error is returned. Otherwise 0 means success. If the
180 * image is interpreted, loop back up and try activating
181 * the interpreter.
182 */
183 for (i = 0; execsw[i]; ++i) {
184 if (execsw[i]->ex_imgact)
185 error = (*execsw[i]->ex_imgact)(imgp);
186 else
187 continue;
188
189 if (error == -1)
190 continue;
191 if (error)
192 goto exec_fail_dealloc;
193 if (imgp->interpreted) {
194 /* free old vnode and name buffer */
195 vrele(ndp->ni_vp);
196 FREE(ndp->ni_cnd.cn_pnbuf, M_NAMEI);
197 if (vm_map_remove(kernel_map, (vm_offset_t)imgp->image_header,
198 (vm_offset_t)imgp->image_header + PAGE_SIZE))
199 panic("execve: header dealloc failed (1)");
200
201 /* set new name to that of the interpreter */
202 NDINIT(ndp, LOOKUP, LOCKLEAF | FOLLOW | SAVENAME,
203 UIO_SYSSPACE, imgp->interpreter_name, p);
204 goto interpret;
205 }
206 break;
207 }
208 /* If we made it through all the activators and none matched, exit. */
209 if (error == -1) {
210 error = ENOEXEC;
211 goto exec_fail_dealloc;
212 }
213
214 /*
215 * Copy out strings (args and env) and initialize stack base
216 */
217 stack_base = exec_copyout_strings(imgp);
218 p->p_vmspace->vm_minsaddr = (char *)stack_base;
219
220 /*
221 * If custom stack fixup routine present for this process
222 * let it do the stack setup.
223 * Else stuff argument count as first item on stack
224 */
225 if (p->p_sysent->sv_fixup)
226 (*p->p_sysent->sv_fixup)(&stack_base, imgp);
227 else
228 suword(--stack_base, imgp->argc);
229
230 /* close files on exec */
231 fdcloseexec(p);
232
233 /* reset caught signals */
234 execsigs(p);
235
236 /* name this process - nameiexec(p, ndp) */
237 len = min(ndp->ni_cnd.cn_namelen,MAXCOMLEN);
238 bcopy(ndp->ni_cnd.cn_nameptr, p->p_comm, len);
239 p->p_comm[len] = 0;
240
241 /*
242 * mark as executable, wakeup any process that was vforked and tell
243 * it that it now has it's own resources back
244 */
245 p->p_flag |= P_EXEC;
246 if (p->p_pptr && (p->p_flag & P_PPWAIT)) {
247 p->p_flag &= ~P_PPWAIT;
248 wakeup((caddr_t)p->p_pptr);
249 }
250
251 /*
252 * Implement image setuid/setgid. Disallow if the process is
253 * being traced.
254 */
255 if ((attr.va_mode & (VSUID | VSGID)) &&
256 (p->p_flag & P_TRACED) == 0) {
257 /*
258 * Turn off syscall tracing for set-id programs, except for
259 * root.
260 */
261 if (p->p_tracep && suser(p->p_ucred, &p->p_acflag)) {
262 p->p_traceflag = 0;
263 vrele(p->p_tracep);
264 p->p_tracep = NULL;
265 }
266 /*
267 * Set the new credentials.
268 */
269 p->p_ucred = crcopy(p->p_ucred);
270 if (attr.va_mode & VSUID)
271 p->p_ucred->cr_uid = attr.va_uid;
272 if (attr.va_mode & VSGID)
273 p->p_ucred->cr_groups[0] = attr.va_gid;
274 p->p_flag |= P_SUGID;
275 } else {
276 p->p_flag &= ~P_SUGID;
277 }
278
279 /*
280 * Implement correct POSIX saved-id behavior.
281 */
282 p->p_cred->p_svuid = p->p_ucred->cr_uid;
283 p->p_cred->p_svgid = p->p_ucred->cr_gid;
284
285 /*
286 * Store the vp for use in procfs
287 */
288 if (p->p_textvp) /* release old reference */
289 vrele(p->p_textvp);
290 VREF(ndp->ni_vp);
291 p->p_textvp = ndp->ni_vp;
292
293 /*
294 * If tracing the process, trap to debugger so breakpoints
295 * can be set before the program executes.
296 */
297 if (p->p_flag & P_TRACED)
298 psignal(p, SIGTRAP);
299
300 /* clear "fork but no exec" flag, as we _are_ execing */
301 p->p_acflag &= ~AFORK;
302
303 /* Set entry address */
304 setregs(p, imgp->entry_addr, (u_long)stack_base);
305
306 /*
307 * free various allocated resources
308 */
309 kmem_free(exec_map, (vm_offset_t)imgp->stringbase, ARG_MAX);
310 if (vm_map_remove(kernel_map, (vm_offset_t)imgp->image_header,
311 (vm_offset_t)imgp->image_header + PAGE_SIZE))
312 panic("execve: header dealloc failed (2)");
313 vrele(ndp->ni_vp);
314 FREE(ndp->ni_cnd.cn_pnbuf, M_NAMEI);
315
316 return (0);
317
318exec_fail_dealloc:
319 if (imgp->stringbase != NULL)
320 kmem_free(exec_map, (vm_offset_t)imgp->stringbase, ARG_MAX);
321 if (imgp->image_header && imgp->image_header != (char *)-1)
322 if (vm_map_remove(kernel_map, (vm_offset_t)imgp->image_header,
323 (vm_offset_t)imgp->image_header + PAGE_SIZE))
324 panic("execve: header dealloc failed (3)");
325 if (ndp->ni_vp)
326 vrele(ndp->ni_vp);
327 FREE(ndp->ni_cnd.cn_pnbuf, M_NAMEI);
328
329exec_fail:
330 if (imgp->vmspace_destroyed) {
331 /* sorry, no more process anymore. exit gracefully */
332 exit1(p, W_EXITCODE(0, SIGABRT));
333 /* NOT REACHED */
334 return(0);
335 } else {
336 return(error);
337 }
338}
339
340/*
341 * Destroy old address space, and allocate a new stack
342 * The new stack is only SGROWSIZ large because it is grown
343 * automatically in trap.c.
344 */
345int
346exec_new_vmspace(imgp)
347 struct image_params *imgp;
348{
349 int error;
350 struct vmspace *vmspace = imgp->proc->p_vmspace;
351 caddr_t stack_addr = (caddr_t) (USRSTACK - SGROWSIZ);
352
353 imgp->vmspace_destroyed = 1;
354
355 /* Blow away entire process VM */
356#ifdef SYSVSHM
357 if (vmspace->vm_shm)
358 shmexit(imgp->proc);
359#endif
360 vm_map_remove(&vmspace->vm_map, 0, USRSTACK);
361
362 /* Allocate a new stack */
363 error = vm_map_find(&vmspace->vm_map, NULL, 0, (vm_offset_t *)&stack_addr,
364 SGROWSIZ, FALSE);
365 if (error)
366 return(error);
367
368 vmspace->vm_ssize = SGROWSIZ >> PAGE_SHIFT;
369
370 /* Initialize maximum stack address */
371 vmspace->vm_maxsaddr = (char *)USRSTACK - MAXSSIZ;
372
373 return(0);
374}
375
376/*
377 * Copy out argument and environment strings from the old process
378 * address space into the temporary string buffer.
379 */
380int
381exec_extract_strings(imgp)
382 struct image_params *imgp;
383{
384 char **argv, **envv;
385 char *argp, *envp;
386 int error, length;
387
388 /*
389 * extract arguments first
390 */
391
392 argv = imgp->uap->argv;
393
394 if (argv) {
395 while ((argp = (caddr_t) fuword(argv++))) {
396 if (argp == (caddr_t) -1)
397 return (EFAULT);
398 if ((error = copyinstr(argp, imgp->stringp,
399 imgp->stringspace, &length))) {
400 if (error == ENAMETOOLONG)
401 return(E2BIG);
402 return (error);
403 }
404 imgp->stringspace -= length;
405 imgp->stringp += length;
406 imgp->argc++;
407 }
408 }
409
410 /*
411 * extract environment strings
412 */
413
414 envv = imgp->uap->envv;
415
416 if (envv) {
417 while ((envp = (caddr_t) fuword(envv++))) {
418 if (envp == (caddr_t) -1)
419 return (EFAULT);
420 if ((error = copyinstr(envp, imgp->stringp,
421 imgp->stringspace, &length))) {
422 if (error == ENAMETOOLONG)
423 return(E2BIG);
424 return (error);
425 }
426 imgp->stringspace -= length;
427 imgp->stringp += length;
428 imgp->envc++;
429 }
430 }
431
432 return (0);
433}
434
435/*
436 * Copy strings out to the new process address space, constructing
437 * new arg and env vector tables. Return a pointer to the base
438 * so that it can be used as the initial stack pointer.
439 */
440int *
441exec_copyout_strings(imgp)
442 struct image_params *imgp;
443{
444 int argc, envc;
445 char **vectp;
446 char *stringp, *destp;
447 int *stack_base;
448 struct ps_strings *arginfo;
449
450 /*
451 * Calculate string base and vector table pointers.
452 */
453 arginfo = PS_STRINGS;
454 destp = (caddr_t)arginfo - SPARE_USRSPACE -
455 roundup((ARG_MAX - imgp->stringspace), sizeof(char *));
456
457 /*
458 * The '+ 2' is for the null pointers at the end of each of the
459 * arg and env vector sets
460 */
461 vectp = (char **) (destp -
462 (imgp->argc + imgp->envc + 2) * sizeof(char *));
463
464 /*
465 * vectp also becomes our initial stack base
466 */
467 stack_base = (int *)vectp;
468
469 stringp = imgp->stringbase;
470 argc = imgp->argc;
471 envc = imgp->envc;
472
473 /*
474 * Copy out strings - arguments and environment.
475 */
476 copyout(stringp, destp, ARG_MAX - imgp->stringspace);
477
478 /*
479 * Fill in "ps_strings" struct for ps, w, etc.
480 */
481 suword(&arginfo->ps_argvstr, (int)vectp);
482 suword(&arginfo->ps_nargvstr, argc);
483
484 /*
485 * Fill in argument portion of vector table.
486 */
487 for (; argc > 0; --argc) {
488 suword(vectp++, (int)destp);
489 while (*stringp++ != 0)
490 destp++;
491 destp++;
492 }
493
494 /* a null vector table pointer seperates the argp's from the envp's */
495 suword(vectp++, NULL);
496
497 suword(&arginfo->ps_envstr, (int)vectp);
498 suword(&arginfo->ps_nenvstr, envc);
499
500 /*
501 * Fill in environment portion of vector table.
502 */
503 for (; envc > 0; --envc) {
504 suword(vectp++, (int)destp);
505 while (*stringp++ != 0)
506 destp++;
507 destp++;
508 }
509
510 /* end of vector table is a null pointer */
511 suword(vectp, NULL);
512
513 return (stack_base);
514}
515
516/*
517 * Check permissions of file to execute.
518 * Return 0 for success or error code on failure.
519 */
520static int
521exec_check_permissions(imgp)
522 struct image_params *imgp;
523{
524 struct proc *p = imgp->proc;
525 struct vnode *vp = imgp->vp;
526 struct vattr *attr = imgp->attr;
527 int error;
528
529 /*
530 * Check number of open-for-writes on the file and deny execution
531 * if there are any.
532 */
533 if (vp->v_writecount) {
534 return (ETXTBSY);
535 }
536
537 /* Get file attributes */
538 error = VOP_GETATTR(vp, attr, p->p_ucred, p);
539 if (error)
540 return (error);
541
542 /*
543 * 1) Check if file execution is disabled for the filesystem that this
544 * file resides on.
545 * 2) Insure that at least one execute bit is on - otherwise root
546 * will always succeed, and we don't want to happen unless the
547 * file really is executable.
548 * 3) Insure that the file is a regular file.
549 */
550 if ((vp->v_mount->mnt_flag & MNT_NOEXEC) ||
551 ((attr->va_mode & 0111) == 0) ||
552 (attr->va_type != VREG)) {
553 return (EACCES);
554 }
555
556 /*
557 * Zero length files can't be exec'd
558 */
559 if (attr->va_size == 0)
560 return (ENOEXEC);
561
562 /*
563 * Disable setuid/setgid if the filesystem prohibits it or if
564 * the process is being traced.
565 */
566 if ((vp->v_mount->mnt_flag & MNT_NOSUID) || (p->p_flag & P_TRACED))
567 attr->va_mode &= ~(VSUID | VSGID);
568
569 /*
570 * Check for execute permission to file based on current credentials.
571 * Then call filesystem specific open routine (which does nothing
572 * in the general case).
573 */
574 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
575 if (error)
576 return (error);
577
578 error = VOP_OPEN(vp, FREAD, p->p_ucred, p);
579 if (error)
580 return (error);
581
582 return (0);
583}
72
73#ifndef _SYS_SYSPROTO_H_
74struct execve_args {
75 char *fname;
76 char **argv;
77 char **envv;
78};
79#endif
80
81/*
82 * execve() system call.
83 */
84int
85execve(p, uap, retval)
86 struct proc *p;
87 register struct execve_args *uap;
88 int *retval;
89{
90 struct nameidata nd, *ndp;
91 int *stack_base;
92 int error, len, i;
93 struct image_params image_params, *imgp;
94 struct vattr attr;
95
96 imgp = &image_params;
97
98 /*
99 * Initialize part of the common data
100 */
101 imgp->proc = p;
102 imgp->uap = uap;
103 imgp->attr = &attr;
104 imgp->image_header = NULL;
105 imgp->argc = imgp->envc = 0;
106 imgp->entry_addr = 0;
107 imgp->vmspace_destroyed = 0;
108 imgp->interpreted = 0;
109 imgp->interpreter_name[0] = '\0';
110
111 /*
112 * Allocate temporary demand zeroed space for argument and
113 * environment strings
114 */
115 imgp->stringbase = (char *)kmem_alloc_pageable(exec_map, ARG_MAX);
116 if (imgp->stringbase == NULL) {
117 error = ENOMEM;
118 goto exec_fail;
119 }
120 imgp->stringp = imgp->stringbase;
121 imgp->stringspace = ARG_MAX;
122
123 /*
124 * Translate the file name. namei() returns a vnode pointer
125 * in ni_vp amoung other things.
126 */
127 ndp = &nd;
128 NDINIT(ndp, LOOKUP, LOCKLEAF | FOLLOW | SAVENAME,
129 UIO_USERSPACE, uap->fname, p);
130
131interpret:
132
133 error = namei(ndp);
134 if (error) {
135 kmem_free(exec_map, (vm_offset_t)imgp->stringbase, ARG_MAX);
136 goto exec_fail;
137 }
138
139 imgp->vp = ndp->ni_vp;
140 if (imgp->vp == NULL) {
141 error = ENOEXEC;
142 goto exec_fail_dealloc;
143 }
144
145 /*
146 * Check file permissions (also 'opens' file)
147 */
148 error = exec_check_permissions(imgp);
149
150 /*
151 * Lose the lock on the vnode. It's no longer needed, and must not
152 * exist for the pagefault paging to work below.
153 */
154 VOP_UNLOCK(imgp->vp);
155
156 if (error)
157 goto exec_fail_dealloc;
158
159 /*
160 * Map the image header (first page) of the file into
161 * kernel address space
162 */
163 error = vm_mmap(kernel_map, /* map */
164 (vm_offset_t *)&imgp->image_header, /* address */
165 PAGE_SIZE, /* size */
166 VM_PROT_READ, /* protection */
167 VM_PROT_READ, /* max protection */
168 0, /* flags */
169 (caddr_t)imgp->vp, /* vnode */
170 0); /* offset */
171 if (error) {
172 uprintf("mmap failed: %d\n",error);
173 goto exec_fail_dealloc;
174 }
175
176 /*
177 * Loop through list of image activators, calling each one.
178 * If there is no match, the activator returns -1. If there
179 * is a match, but there was an error during the activation,
180 * the error is returned. Otherwise 0 means success. If the
181 * image is interpreted, loop back up and try activating
182 * the interpreter.
183 */
184 for (i = 0; execsw[i]; ++i) {
185 if (execsw[i]->ex_imgact)
186 error = (*execsw[i]->ex_imgact)(imgp);
187 else
188 continue;
189
190 if (error == -1)
191 continue;
192 if (error)
193 goto exec_fail_dealloc;
194 if (imgp->interpreted) {
195 /* free old vnode and name buffer */
196 vrele(ndp->ni_vp);
197 FREE(ndp->ni_cnd.cn_pnbuf, M_NAMEI);
198 if (vm_map_remove(kernel_map, (vm_offset_t)imgp->image_header,
199 (vm_offset_t)imgp->image_header + PAGE_SIZE))
200 panic("execve: header dealloc failed (1)");
201
202 /* set new name to that of the interpreter */
203 NDINIT(ndp, LOOKUP, LOCKLEAF | FOLLOW | SAVENAME,
204 UIO_SYSSPACE, imgp->interpreter_name, p);
205 goto interpret;
206 }
207 break;
208 }
209 /* If we made it through all the activators and none matched, exit. */
210 if (error == -1) {
211 error = ENOEXEC;
212 goto exec_fail_dealloc;
213 }
214
215 /*
216 * Copy out strings (args and env) and initialize stack base
217 */
218 stack_base = exec_copyout_strings(imgp);
219 p->p_vmspace->vm_minsaddr = (char *)stack_base;
220
221 /*
222 * If custom stack fixup routine present for this process
223 * let it do the stack setup.
224 * Else stuff argument count as first item on stack
225 */
226 if (p->p_sysent->sv_fixup)
227 (*p->p_sysent->sv_fixup)(&stack_base, imgp);
228 else
229 suword(--stack_base, imgp->argc);
230
231 /* close files on exec */
232 fdcloseexec(p);
233
234 /* reset caught signals */
235 execsigs(p);
236
237 /* name this process - nameiexec(p, ndp) */
238 len = min(ndp->ni_cnd.cn_namelen,MAXCOMLEN);
239 bcopy(ndp->ni_cnd.cn_nameptr, p->p_comm, len);
240 p->p_comm[len] = 0;
241
242 /*
243 * mark as executable, wakeup any process that was vforked and tell
244 * it that it now has it's own resources back
245 */
246 p->p_flag |= P_EXEC;
247 if (p->p_pptr && (p->p_flag & P_PPWAIT)) {
248 p->p_flag &= ~P_PPWAIT;
249 wakeup((caddr_t)p->p_pptr);
250 }
251
252 /*
253 * Implement image setuid/setgid. Disallow if the process is
254 * being traced.
255 */
256 if ((attr.va_mode & (VSUID | VSGID)) &&
257 (p->p_flag & P_TRACED) == 0) {
258 /*
259 * Turn off syscall tracing for set-id programs, except for
260 * root.
261 */
262 if (p->p_tracep && suser(p->p_ucred, &p->p_acflag)) {
263 p->p_traceflag = 0;
264 vrele(p->p_tracep);
265 p->p_tracep = NULL;
266 }
267 /*
268 * Set the new credentials.
269 */
270 p->p_ucred = crcopy(p->p_ucred);
271 if (attr.va_mode & VSUID)
272 p->p_ucred->cr_uid = attr.va_uid;
273 if (attr.va_mode & VSGID)
274 p->p_ucred->cr_groups[0] = attr.va_gid;
275 p->p_flag |= P_SUGID;
276 } else {
277 p->p_flag &= ~P_SUGID;
278 }
279
280 /*
281 * Implement correct POSIX saved-id behavior.
282 */
283 p->p_cred->p_svuid = p->p_ucred->cr_uid;
284 p->p_cred->p_svgid = p->p_ucred->cr_gid;
285
286 /*
287 * Store the vp for use in procfs
288 */
289 if (p->p_textvp) /* release old reference */
290 vrele(p->p_textvp);
291 VREF(ndp->ni_vp);
292 p->p_textvp = ndp->ni_vp;
293
294 /*
295 * If tracing the process, trap to debugger so breakpoints
296 * can be set before the program executes.
297 */
298 if (p->p_flag & P_TRACED)
299 psignal(p, SIGTRAP);
300
301 /* clear "fork but no exec" flag, as we _are_ execing */
302 p->p_acflag &= ~AFORK;
303
304 /* Set entry address */
305 setregs(p, imgp->entry_addr, (u_long)stack_base);
306
307 /*
308 * free various allocated resources
309 */
310 kmem_free(exec_map, (vm_offset_t)imgp->stringbase, ARG_MAX);
311 if (vm_map_remove(kernel_map, (vm_offset_t)imgp->image_header,
312 (vm_offset_t)imgp->image_header + PAGE_SIZE))
313 panic("execve: header dealloc failed (2)");
314 vrele(ndp->ni_vp);
315 FREE(ndp->ni_cnd.cn_pnbuf, M_NAMEI);
316
317 return (0);
318
319exec_fail_dealloc:
320 if (imgp->stringbase != NULL)
321 kmem_free(exec_map, (vm_offset_t)imgp->stringbase, ARG_MAX);
322 if (imgp->image_header && imgp->image_header != (char *)-1)
323 if (vm_map_remove(kernel_map, (vm_offset_t)imgp->image_header,
324 (vm_offset_t)imgp->image_header + PAGE_SIZE))
325 panic("execve: header dealloc failed (3)");
326 if (ndp->ni_vp)
327 vrele(ndp->ni_vp);
328 FREE(ndp->ni_cnd.cn_pnbuf, M_NAMEI);
329
330exec_fail:
331 if (imgp->vmspace_destroyed) {
332 /* sorry, no more process anymore. exit gracefully */
333 exit1(p, W_EXITCODE(0, SIGABRT));
334 /* NOT REACHED */
335 return(0);
336 } else {
337 return(error);
338 }
339}
340
341/*
342 * Destroy old address space, and allocate a new stack
343 * The new stack is only SGROWSIZ large because it is grown
344 * automatically in trap.c.
345 */
346int
347exec_new_vmspace(imgp)
348 struct image_params *imgp;
349{
350 int error;
351 struct vmspace *vmspace = imgp->proc->p_vmspace;
352 caddr_t stack_addr = (caddr_t) (USRSTACK - SGROWSIZ);
353
354 imgp->vmspace_destroyed = 1;
355
356 /* Blow away entire process VM */
357#ifdef SYSVSHM
358 if (vmspace->vm_shm)
359 shmexit(imgp->proc);
360#endif
361 vm_map_remove(&vmspace->vm_map, 0, USRSTACK);
362
363 /* Allocate a new stack */
364 error = vm_map_find(&vmspace->vm_map, NULL, 0, (vm_offset_t *)&stack_addr,
365 SGROWSIZ, FALSE);
366 if (error)
367 return(error);
368
369 vmspace->vm_ssize = SGROWSIZ >> PAGE_SHIFT;
370
371 /* Initialize maximum stack address */
372 vmspace->vm_maxsaddr = (char *)USRSTACK - MAXSSIZ;
373
374 return(0);
375}
376
377/*
378 * Copy out argument and environment strings from the old process
379 * address space into the temporary string buffer.
380 */
381int
382exec_extract_strings(imgp)
383 struct image_params *imgp;
384{
385 char **argv, **envv;
386 char *argp, *envp;
387 int error, length;
388
389 /*
390 * extract arguments first
391 */
392
393 argv = imgp->uap->argv;
394
395 if (argv) {
396 while ((argp = (caddr_t) fuword(argv++))) {
397 if (argp == (caddr_t) -1)
398 return (EFAULT);
399 if ((error = copyinstr(argp, imgp->stringp,
400 imgp->stringspace, &length))) {
401 if (error == ENAMETOOLONG)
402 return(E2BIG);
403 return (error);
404 }
405 imgp->stringspace -= length;
406 imgp->stringp += length;
407 imgp->argc++;
408 }
409 }
410
411 /*
412 * extract environment strings
413 */
414
415 envv = imgp->uap->envv;
416
417 if (envv) {
418 while ((envp = (caddr_t) fuword(envv++))) {
419 if (envp == (caddr_t) -1)
420 return (EFAULT);
421 if ((error = copyinstr(envp, imgp->stringp,
422 imgp->stringspace, &length))) {
423 if (error == ENAMETOOLONG)
424 return(E2BIG);
425 return (error);
426 }
427 imgp->stringspace -= length;
428 imgp->stringp += length;
429 imgp->envc++;
430 }
431 }
432
433 return (0);
434}
435
436/*
437 * Copy strings out to the new process address space, constructing
438 * new arg and env vector tables. Return a pointer to the base
439 * so that it can be used as the initial stack pointer.
440 */
441int *
442exec_copyout_strings(imgp)
443 struct image_params *imgp;
444{
445 int argc, envc;
446 char **vectp;
447 char *stringp, *destp;
448 int *stack_base;
449 struct ps_strings *arginfo;
450
451 /*
452 * Calculate string base and vector table pointers.
453 */
454 arginfo = PS_STRINGS;
455 destp = (caddr_t)arginfo - SPARE_USRSPACE -
456 roundup((ARG_MAX - imgp->stringspace), sizeof(char *));
457
458 /*
459 * The '+ 2' is for the null pointers at the end of each of the
460 * arg and env vector sets
461 */
462 vectp = (char **) (destp -
463 (imgp->argc + imgp->envc + 2) * sizeof(char *));
464
465 /*
466 * vectp also becomes our initial stack base
467 */
468 stack_base = (int *)vectp;
469
470 stringp = imgp->stringbase;
471 argc = imgp->argc;
472 envc = imgp->envc;
473
474 /*
475 * Copy out strings - arguments and environment.
476 */
477 copyout(stringp, destp, ARG_MAX - imgp->stringspace);
478
479 /*
480 * Fill in "ps_strings" struct for ps, w, etc.
481 */
482 suword(&arginfo->ps_argvstr, (int)vectp);
483 suword(&arginfo->ps_nargvstr, argc);
484
485 /*
486 * Fill in argument portion of vector table.
487 */
488 for (; argc > 0; --argc) {
489 suword(vectp++, (int)destp);
490 while (*stringp++ != 0)
491 destp++;
492 destp++;
493 }
494
495 /* a null vector table pointer seperates the argp's from the envp's */
496 suword(vectp++, NULL);
497
498 suword(&arginfo->ps_envstr, (int)vectp);
499 suword(&arginfo->ps_nenvstr, envc);
500
501 /*
502 * Fill in environment portion of vector table.
503 */
504 for (; envc > 0; --envc) {
505 suword(vectp++, (int)destp);
506 while (*stringp++ != 0)
507 destp++;
508 destp++;
509 }
510
511 /* end of vector table is a null pointer */
512 suword(vectp, NULL);
513
514 return (stack_base);
515}
516
517/*
518 * Check permissions of file to execute.
519 * Return 0 for success or error code on failure.
520 */
521static int
522exec_check_permissions(imgp)
523 struct image_params *imgp;
524{
525 struct proc *p = imgp->proc;
526 struct vnode *vp = imgp->vp;
527 struct vattr *attr = imgp->attr;
528 int error;
529
530 /*
531 * Check number of open-for-writes on the file and deny execution
532 * if there are any.
533 */
534 if (vp->v_writecount) {
535 return (ETXTBSY);
536 }
537
538 /* Get file attributes */
539 error = VOP_GETATTR(vp, attr, p->p_ucred, p);
540 if (error)
541 return (error);
542
543 /*
544 * 1) Check if file execution is disabled for the filesystem that this
545 * file resides on.
546 * 2) Insure that at least one execute bit is on - otherwise root
547 * will always succeed, and we don't want to happen unless the
548 * file really is executable.
549 * 3) Insure that the file is a regular file.
550 */
551 if ((vp->v_mount->mnt_flag & MNT_NOEXEC) ||
552 ((attr->va_mode & 0111) == 0) ||
553 (attr->va_type != VREG)) {
554 return (EACCES);
555 }
556
557 /*
558 * Zero length files can't be exec'd
559 */
560 if (attr->va_size == 0)
561 return (ENOEXEC);
562
563 /*
564 * Disable setuid/setgid if the filesystem prohibits it or if
565 * the process is being traced.
566 */
567 if ((vp->v_mount->mnt_flag & MNT_NOSUID) || (p->p_flag & P_TRACED))
568 attr->va_mode &= ~(VSUID | VSGID);
569
570 /*
571 * Check for execute permission to file based on current credentials.
572 * Then call filesystem specific open routine (which does nothing
573 * in the general case).
574 */
575 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
576 if (error)
577 return (error);
578
579 error = VOP_OPEN(vp, FREAD, p->p_ucred, p);
580 if (error)
581 return (error);
582
583 return (0);
584}