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 *
|
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}
|