[BACK]Return to kern_exec.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / kern

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/kern/kern_exec.c between version 1.237 and 1.237.2.4

version 1.237, 2007/02/09 21:55:30 version 1.237.2.4, 2007/05/07 10:55:45
Line 81  __KERNEL_RCSID(0, "$NetBSD$");
Line 81  __KERNEL_RCSID(0, "$NetBSD$");
 #include <machine/cpu.h>  #include <machine/cpu.h>
 #include <machine/reg.h>  #include <machine/reg.h>
   
   #include <compat/common/compat_util.h>
   
 static int exec_sigcode_map(struct proc *, const struct emul *);  static int exec_sigcode_map(struct proc *, const struct emul *);
   
 #ifdef DEBUG_EXEC  #ifdef DEBUG_EXEC
Line 191  const struct emul emul_netbsd = {
Line 193  const struct emul emul_netbsd = {
         uvm_default_mapaddr,          uvm_default_mapaddr,
         NULL,          NULL,
         sizeof(ucontext_t),          sizeof(ucontext_t),
           startlwp,
 };  };
   
 #ifdef LKM  #ifdef LKM
Line 239  check_exec(struct lwp *l, struct exec_pa
Line 242  check_exec(struct lwp *l, struct exec_pa
   
         ndp = epp->ep_ndp;          ndp = epp->ep_ndp;
         ndp->ni_cnd.cn_nameiop = LOOKUP;          ndp->ni_cnd.cn_nameiop = LOOKUP;
         ndp->ni_cnd.cn_flags = FOLLOW | LOCKLEAF | SAVENAME;          ndp->ni_cnd.cn_flags = FOLLOW | LOCKLEAF | SAVENAME | TRYEMULROOT;
         /* first get the vnode */          /* first get the vnode */
         if ((error = namei(ndp)) != 0)          if ((error = namei(ndp)) != 0)
                 return error;                  return error;
Line 281  check_exec(struct lwp *l, struct exec_pa
Line 284  check_exec(struct lwp *l, struct exec_pa
 #endif /* NVERIEXEC > 0 */  #endif /* NVERIEXEC > 0 */
   
 #ifdef PAX_SEGVGUARD  #ifdef PAX_SEGVGUARD
         error = pax_segvguard(l, vp, ndp->ni_cnd.cn_pnbuf, FALSE);          error = pax_segvguard(l, vp, ndp->ni_cnd.cn_pnbuf, false);
         if (error)          if (error)
                 goto bad2;                  goto bad2;
 #endif /* PAX_SEGVGUARD */  #endif /* PAX_SEGVGUARD */
Line 307  check_exec(struct lwp *l, struct exec_pa
Line 310  check_exec(struct lwp *l, struct exec_pa
          * address space           * address space
          */           */
         error = ENOEXEC;          error = ENOEXEC;
         for (i = 0; i < nexecs && error != 0; i++) {          for (i = 0; i < nexecs; i++) {
                 int newerror;                  int newerror;
   
                 epp->ep_esch = execsw[i];                  epp->ep_esch = execsw[i];
                 newerror = (*execsw[i]->es_makecmds)(l, epp);                  newerror = (*execsw[i]->es_makecmds)(l, epp);
   
                   if (!newerror) {
                           /* Seems ok: check that entry point is sane */
                           if (epp->ep_entry > VM_MAXUSER_ADDRESS) {
                                   error = ENOEXEC;
                                   break;
                           }
   
                           /* check limits */
                           if ((epp->ep_tsize > MAXTSIZ) ||
                               (epp->ep_dsize > (u_quad_t)l->l_proc->p_rlimit
                                                       [RLIMIT_DATA].rlim_cur)) {
                                   error = ENOMEM;
                                   break;
                           }
                           return 0;
                   }
   
                   if (epp->ep_emul_root != NULL) {
                           vrele(epp->ep_emul_root);
                           epp->ep_emul_root = NULL;
                   }
                   if (epp->ep_interp != NULL) {
                           vrele(epp->ep_interp);
                           epp->ep_interp = NULL;
                   }
   
                 /* make sure the first "interesting" error code is saved. */                  /* make sure the first "interesting" error code is saved. */
                 if (!newerror || error == ENOEXEC)                  if (error == ENOEXEC)
                         error = newerror;                          error = newerror;
   
                 /* if es_makecmds call was successful, update epp->ep_es */                  if (epp->ep_flags & EXEC_DESTR)
                 if (!newerror && (epp->ep_flags & EXEC_HASES) == 0)                          /* Error from "#!" code, tidied up by recursive call */
                         epp->ep_es = execsw[i];  
   
                 if (epp->ep_flags & EXEC_DESTR && error != 0)  
                         return error;                          return error;
         }          }
         if (!error) {  
                 /* check that entry point is sane */  
                 if (epp->ep_entry > VM_MAXUSER_ADDRESS)  
                         error = ENOEXEC;  
   
                 /* check limits */  
                 if ((epp->ep_tsize > MAXTSIZ) ||  
                     (epp->ep_dsize >  
                      (u_quad_t)l->l_proc->p_rlimit[RLIMIT_DATA].rlim_cur))  
                         error = ENOMEM;  
   
                 if (!error)  
                         return (0);  
         }  
   
         /*          /*
          * free any vmspace-creation commands,           * free any vmspace-creation commands,
Line 418  execve1(struct lwp *l, const char *path,
Line 431  execve1(struct lwp *l, const char *path,
         ksiginfo_t              ksi;          ksiginfo_t              ksi;
         ksiginfoq_t             kq;          ksiginfoq_t             kq;
 #ifdef SYSTRACE  #ifdef SYSTRACE
         int                     wassugid = ISSET(p->p_flag, P_SUGID);          int                     wassugid = ISSET(p->p_flag, PK_SUGID);
         char                    pathbuf[MAXPATHLEN];          char                    pathbuf[MAXPATHLEN];
         size_t                  pathbuflen;          size_t                  pathbuflen;
 #endif /* SYSTRACE */  #endif /* SYSTRACE */
Line 444  execve1(struct lwp *l, const char *path,
Line 457  execve1(struct lwp *l, const char *path,
          * see exec_script_makecmds().           * see exec_script_makecmds().
          */           */
 #ifdef SYSTRACE  #ifdef SYSTRACE
         if (ISSET(p->p_flag, P_SYSTRACE))          if (ISSET(p->p_flag, PK_SYSTRACE))
                 systrace_execve0(p);                  systrace_execve0(p);
   
         error = copyinstr(path, pathbuf, sizeof(pathbuf),          error = copyinstr(path, pathbuf, sizeof(pathbuf),
Line 452  execve1(struct lwp *l, const char *path,
Line 465  execve1(struct lwp *l, const char *path,
         if (error)          if (error)
                 goto clrflg;                  goto clrflg;
   
         NDINIT(&nid, LOOKUP, NOFOLLOW, UIO_SYSSPACE, pathbuf, l);          NDINIT(&nid, LOOKUP, NOFOLLOW | TRYEMULROOT, UIO_SYSSPACE, pathbuf, l);
 #else  #else
         NDINIT(&nid, LOOKUP, NOFOLLOW, UIO_USERSPACE, path, l);          NDINIT(&nid, LOOKUP, NOFOLLOW | TRYEMULROOT, UIO_USERSPACE, path, l);
 #endif /* SYSTRACE */  #endif /* SYSTRACE */
   
         /*          /*
Line 474  execve1(struct lwp *l, const char *path,
Line 487  execve1(struct lwp *l, const char *path,
         pack.ep_vmcmds.evs_used = 0;          pack.ep_vmcmds.evs_used = 0;
         pack.ep_vap = &attr;          pack.ep_vap = &attr;
         pack.ep_flags = 0;          pack.ep_flags = 0;
           pack.ep_emul_root = NULL;
           pack.ep_interp = NULL;
           pack.ep_esch = NULL;
   
 #ifdef LKM  #ifdef LKM
         rw_enter(&exec_lock, RW_READER);          rw_enter(&exec_lock, RW_READER);
Line 570  execve1(struct lwp *l, const char *path,
Line 586  execve1(struct lwp *l, const char *path,
   
         dp = (char *) ALIGN(dp);          dp = (char *) ALIGN(dp);
   
         szsigcode = pack.ep_es->es_emul->e_esigcode -          szsigcode = pack.ep_esch->es_emul->e_esigcode -
             pack.ep_es->es_emul->e_sigcode;              pack.ep_esch->es_emul->e_sigcode;
   
         /* Now check if args & environ fit into new stack */          /* Now check if args & environ fit into new stack */
         if (pack.ep_flags & EXEC_32)          if (pack.ep_flags & EXEC_32)
                 len = ((argc + envc + 2 + pack.ep_es->es_arglen) *                  len = ((argc + envc + 2 + pack.ep_esch->es_arglen) *
                     sizeof(int) + sizeof(int) + dp + STACKGAPLEN +                      sizeof(int) + sizeof(int) + dp + STACKGAPLEN +
                     szsigcode + sizeof(struct ps_strings) + STACK_PTHREADSPACE)                      szsigcode + sizeof(struct ps_strings) + STACK_PTHREADSPACE)
                     - argp;                      - argp;
         else          else
                 len = ((argc + envc + 2 + pack.ep_es->es_arglen) *                  len = ((argc + envc + 2 + pack.ep_esch->es_arglen) *
                     sizeof(char *) + sizeof(int) + dp + STACKGAPLEN +                      sizeof(char *) + sizeof(int) + dp + STACKGAPLEN +
                     szsigcode + sizeof(struct ps_strings) + STACK_PTHREADSPACE)                      szsigcode + sizeof(struct ps_strings) + STACK_PTHREADSPACE)
                     - argp;                      - argp;
   
   #ifdef STACKLALIGN      /* arm, etc. */
           len = STACKALIGN(len);  /* make the stack "safely" aligned */
   #else
         len = ALIGN(len);       /* make the stack "safely" aligned */          len = ALIGN(len);       /* make the stack "safely" aligned */
   #endif
   
         if (len > pack.ep_ssize) { /* in effect, compare to initial limit */          if (len > pack.ep_ssize) { /* in effect, compare to initial limit */
                 error = ENOMEM;                  error = ENOMEM;
Line 625  execve1(struct lwp *l, const char *path,
Line 645  execve1(struct lwp *l, const char *path,
   
         /* Now map address space */          /* Now map address space */
         vm = p->p_vmspace;          vm = p->p_vmspace;
         vm->vm_taddr = (caddr_t) pack.ep_taddr;          vm->vm_taddr = (void *)pack.ep_taddr;
         vm->vm_tsize = btoc(pack.ep_tsize);          vm->vm_tsize = btoc(pack.ep_tsize);
         vm->vm_daddr = (caddr_t) pack.ep_daddr;          vm->vm_daddr = (void*)pack.ep_daddr;
         vm->vm_dsize = btoc(pack.ep_dsize);          vm->vm_dsize = btoc(pack.ep_dsize);
         vm->vm_ssize = btoc(pack.ep_ssize);          vm->vm_ssize = btoc(pack.ep_ssize);
         vm->vm_maxsaddr = (caddr_t) pack.ep_maxsaddr;          vm->vm_maxsaddr = (void *)pack.ep_maxsaddr;
         vm->vm_minsaddr = (caddr_t) pack.ep_minsaddr;          vm->vm_minsaddr = (void *)pack.ep_minsaddr;
   
         /* create the new process's VM space by running the vmcmds */          /* create the new process's VM space by running the vmcmds */
 #ifdef DIAGNOSTIC  #ifdef DIAGNOSTIC
Line 716  execve1(struct lwp *l, const char *path,
Line 736  execve1(struct lwp *l, const char *path,
 #endif /* __MACHINE_STACK_GROWS_UP */  #endif /* __MACHINE_STACK_GROWS_UP */
   
         /* Now copy argc, args & environ to new stack */          /* Now copy argc, args & environ to new stack */
         error = (*pack.ep_es->es_copyargs)(l, &pack, &arginfo, &stack, argp);          error = (*pack.ep_esch->es_copyargs)(l, &pack, &arginfo, &stack, argp);
         if (error) {          if (error) {
                 DPRINTF(("execve: copyargs failed %d\n", error));                  DPRINTF(("execve: copyargs failed %d\n", error));
                 goto exec_abort;                  goto exec_abort;
Line 752  execve1(struct lwp *l, const char *path,
Line 772  execve1(struct lwp *l, const char *path,
         p->p_comm[len] = 0;          p->p_comm[len] = 0;
         p->p_acflag &= ~AFORK;          p->p_acflag &= ~AFORK;
   
         p->p_flag |= P_EXEC;          p->p_flag |= PK_EXEC;
   
         /*          /*
          * Stop profiling.           * Stop profiling.
Line 768  execve1(struct lwp *l, const char *path,
Line 788  execve1(struct lwp *l, const char *path,
          * exited and exec()/exit() are the only places it will be cleared.           * exited and exec()/exit() are the only places it will be cleared.
          */           */
         if ((p->p_sflag & PS_PPWAIT) != 0) {          if ((p->p_sflag & PS_PPWAIT) != 0) {
                 rw_enter(&proclist_lock, RW_READER);                  mutex_enter(&proclist_lock);
                 mutex_enter(&p->p_smutex);                  mutex_enter(&p->p_smutex);
                 p->p_sflag &= ~PS_PPWAIT;                  p->p_sflag &= ~PS_PPWAIT;
                 cv_broadcast(&p->p_pptr->p_waitcv);                  cv_broadcast(&p->p_pptr->p_waitcv);
                 mutex_exit(&p->p_smutex);                  mutex_exit(&p->p_smutex);
                 rw_exit(&proclist_lock);                  mutex_exit(&proclist_lock);
         }          }
   
         /*          /*
Line 793  execve1(struct lwp *l, const char *path,
Line 813  execve1(struct lwp *l, const char *path,
                  * anything that might block.                   * anything that might block.
                  */                   */
                 proc_crmod_enter();                  proc_crmod_enter();
                 proc_crmod_leave(NULL, NULL, TRUE);                  proc_crmod_leave(NULL, NULL, true);
   
                 /* Make sure file descriptors 0..2 are in use. */                  /* Make sure file descriptors 0..2 are in use. */
                 if ((error = fdcheckstd(l)) != 0) {                  if ((error = fdcheckstd(l)) != 0) {
Line 827  execve1(struct lwp *l, const char *path,
Line 847  execve1(struct lwp *l, const char *path,
                     kauth_cred_getuid(l->l_cred) &&                      kauth_cred_getuid(l->l_cred) &&
                     kauth_cred_getegid(l->l_cred) ==                      kauth_cred_getegid(l->l_cred) ==
                     kauth_cred_getgid(l->l_cred))                      kauth_cred_getgid(l->l_cred))
                         p->p_flag &= ~P_SUGID;                          p->p_flag &= ~PK_SUGID;
         }          }
   
         /*          /*
Line 871  execve1(struct lwp *l, const char *path,
Line 891  execve1(struct lwp *l, const char *path,
         KNOTE(&p->p_klist, NOTE_EXEC);          KNOTE(&p->p_klist, NOTE_EXEC);
   
         /* setup new registers and do misc. setup. */          /* setup new registers and do misc. setup. */
         (*pack.ep_es->es_emul->e_setregs)(l, &pack, (u_long) stack);          (*pack.ep_esch->es_emul->e_setregs)(l, &pack, (u_long) stack);
         if (pack.ep_es->es_setregs)          if (pack.ep_esch->es_setregs)
                 (*pack.ep_es->es_setregs)(l, &pack, (u_long) stack);                  (*pack.ep_esch->es_setregs)(l, &pack, (u_long) stack);
   
         /* map the process's signal trampoline code */          /* map the process's signal trampoline code */
         if (exec_sigcode_map(p, pack.ep_es->es_emul)) {          if (exec_sigcode_map(p, pack.ep_esch->es_emul)) {
                 DPRINTF(("execve: map sigcode failed %d\n", error));                  DPRINTF(("execve: map sigcode failed %d\n", error));
                 goto exec_abort;                  goto exec_abort;
         }          }
   
         free(pack.ep_hdr, M_EXEC);          free(pack.ep_hdr, M_EXEC);
   
           /* The emulation root will usually have been found when we looked
            * for the elf interpreter (or similar), if not look now. */
           if (pack.ep_esch->es_emul->e_path != NULL && pack.ep_emul_root == NULL)
                   emul_find_root(l, &pack);
   
           /* Any old emulation root got removed by fdcloseexec */
           p->p_cwdi->cwdi_edir = pack.ep_emul_root;
           pack.ep_emul_root = NULL;
           if (pack.ep_interp != NULL)
                   vrele(pack.ep_interp);
   
         /*          /*
          * Call emulation specific exec hook. This can setup per-process           * Call emulation specific exec hook. This can setup per-process
          * p->p_emuldata or do any other per-process stuff an emulation needs.           * p->p_emuldata or do any other per-process stuff an emulation needs.
Line 894  execve1(struct lwp *l, const char *path,
Line 925  execve1(struct lwp *l, const char *path,
          * resources held previously by this process.           * resources held previously by this process.
          */           */
         if (p->p_emul && p->p_emul->e_proc_exit          if (p->p_emul && p->p_emul->e_proc_exit
             && p->p_emul != pack.ep_es->es_emul)              && p->p_emul != pack.ep_esch->es_emul)
                 (*p->p_emul->e_proc_exit)(p);                  (*p->p_emul->e_proc_exit)(p);
   
         /*          /*
          * Call exec hook. Emulation code may NOT store reference to anything           * Call exec hook. Emulation code may NOT store reference to anything
          * from &pack.           * from &pack.
          */           */
         if (pack.ep_es->es_emul->e_proc_exec)          if (pack.ep_esch->es_emul->e_proc_exec)
                 (*pack.ep_es->es_emul->e_proc_exec)(p, &pack);                  (*pack.ep_esch->es_emul->e_proc_exec)(p, &pack);
   
         /* update p_emul, the old value is no longer needed */          /* update p_emul, the old value is no longer needed */
         p->p_emul = pack.ep_es->es_emul;          p->p_emul = pack.ep_esch->es_emul;
   
         /* ...and the same for p_execsw */          /* ...and the same for p_execsw */
         p->p_execsw = pack.ep_es;          p->p_execsw = pack.ep_esch;
   
 #ifdef __HAVE_SYSCALL_INTERN  #ifdef __HAVE_SYSCALL_INTERN
         (*p->p_emul->e_syscall_intern)(p);          (*p->p_emul->e_syscall_intern)(p);
Line 945  execve1(struct lwp *l, const char *path,
Line 976  execve1(struct lwp *l, const char *path,
                 p->p_nrlwps--;                  p->p_nrlwps--;
                 mutex_exit(&p->p_smutex);                  mutex_exit(&p->p_smutex);
                 mutex_exit(&proclist_mutex);                  mutex_exit(&proclist_mutex);
                 mi_switch(l, NULL);                  mi_switch(l);
                 ksiginfo_queue_drain(&kq);                  ksiginfo_queue_drain(&kq);
                 KERNEL_LOCK(l->l_biglocks, l);                  KERNEL_LOCK(l->l_biglocks, l);
         } else {          } else {
Line 958  execve1(struct lwp *l, const char *path,
Line 989  execve1(struct lwp *l, const char *path,
   
 #ifdef SYSTRACE  #ifdef SYSTRACE
         /* XXXSMP */          /* XXXSMP */
         if (ISSET(p->p_flag, P_SYSTRACE) &&          if (ISSET(p->p_flag, PK_SYSTRACE) &&
             wassugid && !ISSET(p->p_flag, P_SUGID))              wassugid && !ISSET(p->p_flag, PK_SUGID))
                 systrace_execve1(pathbuf, p);                  systrace_execve1(pathbuf, p);
 #endif /* SYSTRACE */  #endif /* SYSTRACE */
   
Line 982  execve1(struct lwp *l, const char *path,
Line 1013  execve1(struct lwp *l, const char *path,
   
  freehdr:   freehdr:
         free(pack.ep_hdr, M_EXEC);          free(pack.ep_hdr, M_EXEC);
           if (pack.ep_emul_root != NULL)
                   vrele(pack.ep_emul_root);
           if (pack.ep_interp != NULL)
                   vrele(pack.ep_interp);
   
 #ifdef SYSTRACE  #ifdef SYSTRACE
  clrflg:   clrflg:
Line 1013  execve1(struct lwp *l, const char *path,
Line 1048  execve1(struct lwp *l, const char *path,
         PNBUF_PUT(nid.ni_cnd.cn_pnbuf);          PNBUF_PUT(nid.ni_cnd.cn_pnbuf);
         uvm_km_free(exec_map, (vaddr_t) argp, NCARGS, UVM_KMF_PAGEABLE);          uvm_km_free(exec_map, (vaddr_t) argp, NCARGS, UVM_KMF_PAGEABLE);
         free(pack.ep_hdr, M_EXEC);          free(pack.ep_hdr, M_EXEC);
           if (pack.ep_emul_root != NULL)
                   vrele(pack.ep_emul_root);
           if (pack.ep_interp != NULL)
                   vrele(pack.ep_interp);
   
         /*          /*
          * Acquire the sched-state mutex (exit1() will release it).  Since           * Acquire the sched-state mutex (exit1() will release it).  Since
Line 1044  copyargs(struct lwp *l, struct exec_pack
Line 1083  copyargs(struct lwp *l, struct exec_pack
         if ((error = copyout(&argc, cpp++, sizeof(argc))) != 0)          if ((error = copyout(&argc, cpp++, sizeof(argc))) != 0)
                 return error;                  return error;
   
         dp = (char *) (cpp + argc + envc + 2 + pack->ep_es->es_arglen);          dp = (char *) (cpp + argc + envc + 2 + pack->ep_esch->es_arglen);
         sp = argp;          sp = argp;
   
         /* XXX don't copy them out, remap them! */          /* XXX don't copy them out, remap them! */
Line 1160  emul_unregister(const char *name)
Line 1199  emul_unregister(const char *name)
          * emul_unregister() is running quite sendomly, it's better           * emul_unregister() is running quite sendomly, it's better
          * to do expensive check here than to use any locking.           * to do expensive check here than to use any locking.
          */           */
         rw_enter(&proclist_lock, RW_READER);          mutex_enter(&proclist_lock);
         for (pd = proclists; pd->pd_list != NULL && !error; pd++) {          for (pd = proclists; pd->pd_list != NULL && !error; pd++) {
                 PROCLIST_FOREACH(ptmp, pd->pd_list) {                  PROCLIST_FOREACH(ptmp, pd->pd_list) {
                         if (ptmp->p_emul == it->el_emul) {                          if (ptmp->p_emul == it->el_emul) {
Line 1169  emul_unregister(const char *name)
Line 1208  emul_unregister(const char *name)
                         }                          }
                 }                  }
         }          }
         rw_exit(&proclist_lock);          mutex_exit(&proclist_lock);
   
         if (error)          if (error)
                 goto out;                  goto out;

Legend:
Removed from v.1.237  
changed lines
  Added in v.1.237.2.4

CVSweb <webmaster@jp.NetBSD.org>