diff options
author | Maxim Sobolev <sobomax@FreeBSD.org> | 2005-01-29 23:12:00 +0000 |
---|---|---|
committer | Maxim Sobolev <sobomax@FreeBSD.org> | 2005-01-29 23:12:00 +0000 |
commit | 610ecfe035fa08e39d4f6f6a247a16b7e60188e7 (patch) | |
tree | c697d47092272c8c6973b42ba0a424e9763f7ce5 /sys | |
parent | 3fcd9325ec61ead859015f90f524cda56ef9d347 (diff) | |
download | src-610ecfe035fa08e39d4f6f6a247a16b7e60188e7.tar.gz src-610ecfe035fa08e39d4f6f6a247a16b7e60188e7.zip |
o Split out kernel part of execve(2) syscall into two parts: one that
copies arguments into the kernel space and one that operates
completely in the kernel space;
o use kernel-only version of execve(2) to kill another stackgap in
linuxlator/i386.
Obtained from: DragonFlyBSD (partially)
MFC after: 2 weeks
Notes
Notes:
svn path=/head/; revision=140992
Diffstat (limited to 'sys')
-rw-r--r-- | sys/alpha/linux/linux_sysvec.c | 8 | ||||
-rw-r--r-- | sys/alpha/osf1/imgact_osf1.c | 7 | ||||
-rw-r--r-- | sys/alpha/osf1/osf1_sysvec.c | 8 | ||||
-rw-r--r-- | sys/amd64/linux32/linux32_sysvec.c | 18 | ||||
-rw-r--r-- | sys/compat/ia32/ia32_sysvec.c | 14 | ||||
-rw-r--r-- | sys/compat/pecoff/imgact_pecoff.c | 8 | ||||
-rw-r--r-- | sys/compat/svr4/imgact_svr4.c | 5 | ||||
-rw-r--r-- | sys/compat/svr4/svr4_sysvec.c | 4 | ||||
-rw-r--r-- | sys/i386/ibcs2/ibcs2_sysvec.c | 2 | ||||
-rw-r--r-- | sys/i386/ibcs2/imgact_coff.c | 5 | ||||
-rw-r--r-- | sys/i386/linux/imgact_linux.c | 5 | ||||
-rw-r--r-- | sys/i386/linux/linux_machdep.c | 26 | ||||
-rw-r--r-- | sys/i386/linux/linux_sysvec.c | 8 | ||||
-rw-r--r-- | sys/kern/imgact_aout.c | 7 | ||||
-rw-r--r-- | sys/kern/imgact_elf.c | 11 | ||||
-rw-r--r-- | sys/kern/imgact_gzip.c | 6 | ||||
-rw-r--r-- | sys/kern/imgact_shell.c | 138 | ||||
-rw-r--r-- | sys/kern/kern_exec.c | 208 | ||||
-rw-r--r-- | sys/kern/kern_kse.c | 8 | ||||
-rw-r--r-- | sys/modules/Makefile | 2 | ||||
-rw-r--r-- | sys/sys/imgact.h | 27 | ||||
-rw-r--r-- | sys/sys/syscallsubr.h | 3 |
22 files changed, 287 insertions, 241 deletions
diff --git a/sys/alpha/linux/linux_sysvec.c b/sys/alpha/linux/linux_sysvec.c index e3b91eeb2e56..a09dfdcd0abd 100644 --- a/sys/alpha/linux/linux_sysvec.c +++ b/sys/alpha/linux/linux_sysvec.c @@ -97,7 +97,7 @@ elf_linux_fixup(register_t **stack_base, struct image_params *imgp) (curthread->td_proc->p_flag & P_SA) == 0, ("unsafe elf_linux_fixup(), should be curproc")); args = (Elf64_Auxargs *)imgp->auxargs; - pos = *stack_base + (imgp->argc + imgp->envc + 2); + pos = *stack_base + (imgp->args->argc + imgp->args->envc + 2); if (args->trace) AUXARGS_ENTRY(pos, AT_DEBUG, 1); @@ -120,7 +120,7 @@ elf_linux_fixup(register_t **stack_base, struct image_params *imgp) imgp->auxargs = NULL; (*stack_base)--; - **stack_base = (register_t)imgp->argc; + **stack_base = (register_t)imgp->args->argc; return 0; } @@ -154,8 +154,8 @@ exec_linux_imgact_try(imgp) if ((error = exec_shell_imgact(imgp)) == 0) { char *rpath = NULL; - linux_emul_find(FIRST_THREAD_IN_PROC(imgp->proc), NULL, - imgp->interpreter_name, &rpath, 0); + linux_emul_convpath(FIRST_THREAD_IN_PROC(imgp->proc), + imgp->interpreter_name, UIO_SYSSPACE, &rpath, 0); if (rpath != imgp->interpreter_name) { int len = strlen(rpath) + 1; diff --git a/sys/alpha/osf1/imgact_osf1.c b/sys/alpha/osf1/imgact_osf1.c index 40520a0dd792..451896f492c7 100644 --- a/sys/alpha/osf1/imgact_osf1.c +++ b/sys/alpha/osf1/imgact_osf1.c @@ -118,7 +118,7 @@ exec_osf1_imgact(struct image_params *imgp) osf_auxargs = malloc(sizeof(Osf_Auxargs), M_TEMP, M_WAITOK | M_ZERO); imgp->auxargs = osf_auxargs; osf_auxargs->executable = osf_auxargs->exec_path; - path_not_saved = copyinstr(imgp->fname, osf_auxargs->executable, + path_not_saved = copystr(imgp->args->fname, osf_auxargs->executable, PATH_MAX, &bytes); if (execp->f.f_flags & DYNAMIC_FLAG) { if (path_not_saved) { @@ -172,11 +172,6 @@ exec_osf1_imgact(struct image_params *imgp) bsize = eap->bsize; imgp->entry_addr = eap->entry; - /* copy in arguments and/or environment from old process */ - - error = exec_extract_strings(imgp); - if (error) - goto bail; /* * Destroy old process VM and create a new one (with a new stack). diff --git a/sys/alpha/osf1/osf1_sysvec.c b/sys/alpha/osf1/osf1_sysvec.c index 0dea307c9d91..818255368215 100644 --- a/sys/alpha/osf1/osf1_sysvec.c +++ b/sys/alpha/osf1/osf1_sysvec.c @@ -117,15 +117,15 @@ osf1_freebsd_fixup(long **stack_base, struct image_params *imgp) Osf_Auxargs *args; args = (Osf_Auxargs *)imgp->auxargs; - pos = *stack_base + (imgp->argc + imgp->envc + 2); + pos = *stack_base + (imgp->args->argc + imgp->args->envc + 2); arginfo = (struct ps_strings *)PS_STRINGS; sz = *(imgp->proc->p_sysent->sv_szsigcode); destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE - - roundup((ARG_MAX - imgp->stringspace), sizeof(char *)); + roundup((ARG_MAX - imgp->args->stringspace), sizeof(char *)); - destp -= imgp->stringspace; + destp -= imgp->args->stringspace; destp -= strlen(args->executable)+2; copyout(args->executable, destp, strlen(args->executable)+1); @@ -143,6 +143,6 @@ osf1_freebsd_fixup(long **stack_base, struct image_params *imgp) free(imgp->auxargs, M_TEMP); imgp->auxargs = NULL; (*stack_base)--; - **stack_base = (long)imgp->argc; + **stack_base = (long)imgp->args->argc; return 0; } diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c index 2b3f75f7f7a0..99ac19098aeb 100644 --- a/sys/amd64/linux32/linux32_sysvec.c +++ b/sys/amd64/linux32/linux32_sysvec.c @@ -246,7 +246,7 @@ elf_linux_fixup(register_t **stack_base, struct image_params *imgp) ("unsafe elf_linux_fixup(), should be curproc")); base = (Elf32_Addr *)*stack_base; args = (Elf32_Auxargs *)imgp->auxargs; - pos = base + (imgp->argc + imgp->envc + 2); + pos = base + (imgp->args->argc + imgp->args->envc + 2); if (args->trace) AUXARGS_ENTRY_32(pos, AT_DEBUG, 1); @@ -269,7 +269,7 @@ elf_linux_fixup(register_t **stack_base, struct image_params *imgp) imgp->auxargs = NULL; base--; - suword32(base, (uint32_t)imgp->argc); + suword32(base, (uint32_t)imgp->args->argc); *stack_base = (register_t *)base; return 0; } @@ -836,7 +836,7 @@ linux_copyout_strings(struct image_params *imgp) arginfo = (struct linux32_ps_strings *)LINUX32_PS_STRINGS; sigcodesz = *(imgp->proc->p_sysent->sv_szsigcode); destp = (caddr_t)arginfo - sigcodesz - SPARE_USRSPACE - - roundup((ARG_MAX - imgp->stringspace), sizeof(char *)); + roundup((ARG_MAX - imgp->args->stringspace), sizeof(char *)); /* * install sigcode @@ -861,7 +861,7 @@ linux_copyout_strings(struct image_params *imgp) * the arg and env vector sets,and imgp->auxarg_size is room * for argument of Runtime loader. */ - vectp = (u_int32_t *) (destp - (imgp->argc + imgp->envc + 2 + + vectp = (u_int32_t *) (destp - (imgp->args->argc + imgp->args->envc + 2 + imgp->auxarg_size) * sizeof(u_int32_t)); } else @@ -870,20 +870,20 @@ linux_copyout_strings(struct image_params *imgp) * the arg and env vector sets */ vectp = (u_int32_t *) - (destp - (imgp->argc + imgp->envc + 2) * sizeof(u_int32_t)); + (destp - (imgp->args->argc + imgp->args->envc + 2) * sizeof(u_int32_t)); /* * vectp also becomes our initial stack base */ stack_base = vectp; - stringp = imgp->stringbase; - argc = imgp->argc; - envc = imgp->envc; + stringp = imgp->args->begin_argv; + argc = imgp->args->argc; + envc = imgp->args->envc; /* * Copy out strings - arguments and environment. */ - copyout(stringp, destp, ARG_MAX - imgp->stringspace); + copyout(stringp, destp, ARG_MAX - imgp->args->stringspace); /* * Fill in "ps_strings" struct for ps, w, etc. diff --git a/sys/compat/ia32/ia32_sysvec.c b/sys/compat/ia32/ia32_sysvec.c index a2d14354b87f..1052d61c0578 100644 --- a/sys/compat/ia32/ia32_sysvec.c +++ b/sys/compat/ia32/ia32_sysvec.c @@ -183,7 +183,7 @@ ia32_copyout_strings(struct image_params *imgp) arginfo = (struct freebsd32_ps_strings *)FREEBSD32_PS_STRINGS; szsigcode = *(imgp->proc->p_sysent->sv_szsigcode); destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE - - roundup((ARG_MAX - imgp->stringspace), sizeof(char *)); + roundup((ARG_MAX - imgp->args->stringspace), sizeof(char *)); /* * install sigcode @@ -208,7 +208,7 @@ ia32_copyout_strings(struct image_params *imgp) * the arg and env vector sets,and imgp->auxarg_size is room * for argument of Runtime loader. */ - vectp = (u_int32_t *) (destp - (imgp->argc + imgp->envc + 2 + + vectp = (u_int32_t *) (destp - (imgp->args->argc + imgp->args->envc + 2 + imgp->auxarg_size) * sizeof(u_int32_t)); } else @@ -217,20 +217,20 @@ ia32_copyout_strings(struct image_params *imgp) * the arg and env vector sets */ vectp = (u_int32_t *) - (destp - (imgp->argc + imgp->envc + 2) * sizeof(u_int32_t)); + (destp - (imgp->args->argc + imgp->args->envc + 2) * sizeof(u_int32_t)); /* * vectp also becomes our initial stack base */ stack_base = vectp; - stringp = imgp->stringbase; - argc = imgp->argc; - envc = imgp->envc; + stringp = imgp->args->begin_argv; + argc = imgp->args->argc; + envc = imgp->args->envc; /* * Copy out strings - arguments and environment. */ - copyout(stringp, destp, ARG_MAX - imgp->stringspace); + copyout(stringp, destp, ARG_MAX - imgp->args->stringspace); /* * Fill in "ps_strings" struct for ps, w, etc. diff --git a/sys/compat/pecoff/imgact_pecoff.c b/sys/compat/pecoff/imgact_pecoff.c index b15c65cb904d..203910306c85 100644 --- a/sys/compat/pecoff/imgact_pecoff.c +++ b/sys/compat/pecoff/imgact_pecoff.c @@ -149,7 +149,7 @@ pecoff_fixup(register_t ** stack_base, struct image_params * imgp) struct pecoff_imghdr *ap; register_t *pos; - pos = *stack_base + (imgp->argc + imgp->envc + 2); + pos = *stack_base + (imgp->args->argc + imgp->args->envc + 2); ap = (struct pecoff_imghdr *) imgp->auxargs; if (copyout(ap, pos, len)) { return 0; @@ -157,7 +157,7 @@ pecoff_fixup(register_t ** stack_base, struct image_params * imgp) free(ap, M_TEMP); imgp->auxargs = NULL; (*stack_base)--; - suword(*stack_base, (long) imgp->argc); + suword(*stack_base, (long) imgp->args->argc); return 0; } @@ -299,8 +299,6 @@ pecoff_load_file(struct thread * td, const char *file, u_long * addr, u_long * e * Initialize part of the common data */ imgp->proc = td->td_proc; - imgp->userspace_argv = NULL; - imgp->userspace_envv = NULL; imgp->execlabel = NULL; imgp->attr = &attr; imgp->firstpage = NULL; @@ -418,8 +416,6 @@ exec_pecoff_coff_prep_zmagic(struct image_params * imgp, wp = (void *) ((char *) ap + sizeof(struct coff_aouthdr)); error = pecoff_read_from(FIRST_THREAD_IN_PROC(imgp->proc), imgp->vp, peofs + PECOFF_HDR_SIZE, (caddr_t) sh, scnsiz); - if ((error = exec_extract_strings(imgp)) != 0) - goto fail; exec_new_vmspace(imgp, &pecoff_sysvec); vmspace = imgp->proc->p_vmspace; for (i = 0; i < fp->f_nscns; i++) { diff --git a/sys/compat/svr4/imgact_svr4.c b/sys/compat/svr4/imgact_svr4.c index 90d3b384e0a6..39eeb99369ee 100644 --- a/sys/compat/svr4/imgact_svr4.c +++ b/sys/compat/svr4/imgact_svr4.c @@ -117,11 +117,6 @@ exec_svr4_imgact(imgp) VOP_UNLOCK(imgp->vp, 0, td); - /* copy in arguments and/or environment from old process */ - error = exec_extract_strings(imgp); - if (error) - goto fail; - /* * Destroy old process VM and create a new one (with a new stack) */ diff --git a/sys/compat/svr4/svr4_sysvec.c b/sys/compat/svr4/svr4_sysvec.c index 496901ae562d..80e54b0cb5f6 100644 --- a/sys/compat/svr4/svr4_sysvec.c +++ b/sys/compat/svr4/svr4_sysvec.c @@ -215,7 +215,7 @@ svr4_fixup(register_t **stack_base, struct image_params *imgp) (curthread->td_proc->p_flag & P_SA) == 0, ("unsafe svr4_fixup(), should be curproc")); args = (Elf32_Auxargs *)imgp->auxargs; - pos = *stack_base + (imgp->argc + imgp->envc + 2); + pos = *stack_base + (imgp->args->argc + imgp->args->envc + 2); if (args->trace) AUXARGS_ENTRY(pos, AT_DEBUG, 1); @@ -238,7 +238,7 @@ svr4_fixup(register_t **stack_base, struct image_params *imgp) imgp->auxargs = NULL; (*stack_base)--; - **stack_base = (register_t)imgp->argc; + **stack_base = (register_t)imgp->args->argc; return 0; } diff --git a/sys/i386/ibcs2/ibcs2_sysvec.c b/sys/i386/ibcs2/ibcs2_sysvec.c index 6a4dacccefe4..74be78238e5e 100644 --- a/sys/i386/ibcs2/ibcs2_sysvec.c +++ b/sys/i386/ibcs2/ibcs2_sysvec.c @@ -91,7 +91,7 @@ static int ibcs2_fixup(register_t **stack_base, struct image_params *imgp) { - return (suword(--(*stack_base), imgp->argc)); + return (suword(--(*stack_base), imgp->args->argc)); } /* diff --git a/sys/i386/ibcs2/imgact_coff.c b/sys/i386/ibcs2/imgact_coff.c index 6470813236d6..226d1e979b64 100644 --- a/sys/i386/ibcs2/imgact_coff.c +++ b/sys/i386/ibcs2/imgact_coff.c @@ -332,11 +332,6 @@ exec_coff_imgact(imgp) VOP_UNLOCK(imgp->vp, 0, td); - if ((error = exec_extract_strings(imgp)) != 0) { - DPRINTF(("%s(%d): return %d\n", __FILE__, __LINE__, error)); - goto fail; - } - exec_new_vmspace(imgp, &ibcs2_svr3_sysvec); vmspace = imgp->proc->p_vmspace; diff --git a/sys/i386/linux/imgact_linux.c b/sys/i386/linux/imgact_linux.c index 093abfb840a6..50e40bf3c2b0 100644 --- a/sys/i386/linux/imgact_linux.c +++ b/sys/i386/linux/imgact_linux.c @@ -116,11 +116,6 @@ exec_linux_imgact(struct image_params *imgp) VOP_UNLOCK(imgp->vp, 0, td); - /* copy in arguments and/or environment from old process */ - error = exec_extract_strings(imgp); - if (error) - goto fail; - /* * Destroy old process VM and create a new one (with a new stack) */ diff --git a/sys/i386/linux/linux_machdep.c b/sys/i386/linux/linux_machdep.c index 2a825e8cab8c..77c49b121677 100644 --- a/sys/i386/linux/linux_machdep.c +++ b/sys/i386/linux/linux_machdep.c @@ -31,7 +31,9 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/systm.h> +#include <sys/imgact.h> #include <sys/lock.h> +#include <sys/malloc.h> #include <sys/mman.h> #include <sys/mutex.h> #include <sys/proc.h> @@ -104,21 +106,27 @@ bsd_to_linux_sigaltstack(int bsa) int linux_execve(struct thread *td, struct linux_execve_args *args) { - struct execve_args bsd; - caddr_t sg; + int error; + char *newpath; + struct image_args eargs; - sg = stackgap_init(); - CHECKALTEXIST(td, &sg, args->path); + error = linux_emul_convpath(td, args->path, UIO_USERSPACE, + &newpath, 0); + if (newpath == NULL) + return (error); #ifdef DEBUG if (ldebug(execve)) - printf(ARGS(execve, "%s"), args->path); + printf(ARGS(execve, "%s"), newpath); #endif - bsd.fname = args->path; - bsd.argv = args->argp; - bsd.envv = args->envp; - return (execve(td, &bsd)); + error = exec_copyin_args(&eargs, newpath, UIO_SYSSPACE, + args->argp, args->envp); + free(newpath, M_TEMP); + if (error == 0) + kern_execve(td, &eargs, NULL); + exec_free_args(&eargs); + return (error); } struct l_ipc_kludge { diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c index 11f8981f99ec..859270148d90 100644 --- a/sys/i386/linux/linux_sysvec.c +++ b/sys/i386/linux/linux_sysvec.c @@ -216,13 +216,13 @@ linux_fixup(register_t **stack_base, struct image_params *imgp) register_t *argv, *envp; argv = *stack_base; - envp = *stack_base + (imgp->argc + 1); + envp = *stack_base + (imgp->args->argc + 1); (*stack_base)--; **stack_base = (intptr_t)(void *)envp; (*stack_base)--; **stack_base = (intptr_t)(void *)argv; (*stack_base)--; - **stack_base = imgp->argc; + **stack_base = imgp->args->argc; return 0; } @@ -236,7 +236,7 @@ elf_linux_fixup(register_t **stack_base, struct image_params *imgp) (curthread->td_proc->p_flag & P_SA) == 0, ("unsafe elf_linux_fixup(), should be curproc")); args = (Elf32_Auxargs *)imgp->auxargs; - pos = *stack_base + (imgp->argc + imgp->envc + 2); + pos = *stack_base + (imgp->args->argc + imgp->args->envc + 2); if (args->trace) AUXARGS_ENTRY(pos, AT_DEBUG, 1); @@ -259,7 +259,7 @@ elf_linux_fixup(register_t **stack_base, struct image_params *imgp) imgp->auxargs = NULL; (*stack_base)--; - **stack_base = (register_t)imgp->argc; + **stack_base = (register_t)imgp->args->argc; return 0; } diff --git a/sys/kern/imgact_aout.c b/sys/kern/imgact_aout.c index 9263384ebf7b..12086fa3a06f 100644 --- a/sys/kern/imgact_aout.c +++ b/sys/kern/imgact_aout.c @@ -90,7 +90,7 @@ aout_fixup(stack_base, imgp) struct image_params *imgp; { - return (suword(--(*stack_base), imgp->argc)); + return (suword(--(*stack_base), imgp->args->argc)); } static int @@ -187,11 +187,6 @@ exec_aout_imgact(imgp) } PROC_UNLOCK(imgp->proc); - /* copy in arguments and/or environment from old process */ - error = exec_extract_strings(imgp); - if (error) - return (error); - /* * Destroy old process VM and create a new one (with a new stack) */ diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index ee723e922d68..03e7f9077e46 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -528,8 +528,6 @@ __elfN(load_file)(struct proc *p, const char *file, u_long *addr, * Initialize part of the common data */ imgp->proc = p; - imgp->userspace_argv = NULL; - imgp->userspace_envv = NULL; imgp->attr = attr; imgp->firstpage = NULL; imgp->image_header = NULL; @@ -647,7 +645,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) u_long text_addr = 0, data_addr = 0; u_long seg_size, seg_addr; u_long addr, entry = 0, proghdr = 0; - int error, i; + int error = 0, i; const char *interp = NULL; Elf_Brandinfo *brand_info; char *path; @@ -706,9 +704,6 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) if (interp != NULL && brand_info->interp_newpath != NULL) interp = brand_info->interp_newpath; - if ((error = exec_extract_strings(imgp)) != 0) - goto fail; - exec_new_vmspace(imgp, sv); vmspace = imgp->proc->p_vmspace; @@ -879,7 +874,7 @@ __elfN(freebsd_fixup)(register_t **stack_base, struct image_params *imgp) Elf_Addr *pos; base = (Elf_Addr *)*stack_base; - pos = base + (imgp->argc + imgp->envc + 2); + pos = base + (imgp->args->argc + imgp->args->envc + 2); if (args->trace) { AUXARGS_ENTRY(pos, AT_DEBUG, 1); @@ -900,7 +895,7 @@ __elfN(freebsd_fixup)(register_t **stack_base, struct image_params *imgp) imgp->auxargs = NULL; base--; - suword(base, (long)imgp->argc); + suword(base, (long)imgp->args->argc); *stack_base = (register_t *)base; return (0); } diff --git a/sys/kern/imgact_gzip.c b/sys/kern/imgact_gzip.c index 0885976eb7f6..d44d49dbe7b1 100644 --- a/sys/kern/imgact_gzip.c +++ b/sys/kern/imgact_gzip.c @@ -225,12 +225,6 @@ do_aout_hdr(struct imgact_gzip * gz) /* Find out how far we should go */ gz->file_end = gz->file_offset + gz->a_out.a_text + gz->a_out.a_data; - /* copy in arguments and/or environment from old process */ - error = exec_extract_strings(gz->ip); - if (error) { - gz->where = __LINE__; - return (error); - } /* * Destroy old process VM and create a new one (with a new stack) */ diff --git a/sys/kern/imgact_shell.c b/sys/kern/imgact_shell.c index b34e0c148f1d..07bcd574a957 100644 --- a/sys/kern/imgact_shell.c +++ b/sys/kern/imgact_shell.c @@ -42,15 +42,15 @@ __FBSDID("$FreeBSD$"); /* * Shell interpreter image activator. An interpreter name beginning - * at imgp->stringbase is the minimal successful exit requirement. + * at imgp->args->begin_argv is the minimal successful exit requirement. */ int exec_shell_imgact(imgp) struct image_params *imgp; { const char *image_header = imgp->image_header; - const char *ihp, *line_endp; - char *interp; + const char *ihp; + int error, length, offset; /* a shell script? */ if (((const short *) image_header)[0] != SHELLMAGIC) @@ -66,64 +66,110 @@ exec_shell_imgact(imgp) imgp->interpreted = 1; /* - * Copy shell name and arguments from image_header into string - * buffer. + * Figure out the number of bytes that need to be reserved in the + * argument string to copy the contents of the interpreter's command + * line into the argument string. */ + ihp = &image_header[2]; + offset = 0; + while (ihp < &image_header[MAXSHELLCMDLEN]) { + /* Skip any whitespace */ + while ((*ihp == ' ') || (*ihp == '\t')) { + ihp++; + continue; + } + + /* End of line? */ + if ((*ihp == '\n') || (*ihp == '#')) + break; + + /* Found a token */ + while ((*ihp != ' ') && (*ihp != '\t') && (*ihp != '\n') && + (*ihp != '#')) { + offset++; + ihp++; + } + /* Include terminating nulls in the offset */ + offset++; + } + + /* If the script gives a null line as the interpreter, we bail */ + if (offset == 0) + return (ENOEXEC); + + /* Check that we aren't too big */ + if (offset > MAXSHELLCMDLEN) + return (ENAMETOOLONG); /* - * Find end of line; return if the line > MAXSHELLCMDLEN long. + * The full path name of the original script file must be tagged + * onto the end, adjust the offset to deal with it. + * + * The original argv[0] is being replaced, set 'length' to the number + * of bytes being removed. So 'offset' is the number of bytes being + * added and 'length' is the number of bytes being removed. */ - for (ihp = &image_header[2]; *ihp != '\n'; ++ihp) { - if (ihp >= &image_header[MAXSHELLCMDLEN]) - return(ENAMETOOLONG); - } - line_endp = ihp; + offset += strlen(imgp->args->fname) + 1; /* add fname */ + length = (imgp->args->argc == 0) ? 0 : + strlen(imgp->args->begin_argv) + 1; /* bytes to delete */ - /* reset for another pass */ - ihp = &image_header[2]; + if (offset - length > imgp->args->stringspace) + return (E2BIG); - /* Skip over leading spaces - until the interpreter name */ - while ((*ihp == ' ') || (*ihp == '\t')) ihp++; + bcopy(imgp->args->begin_argv + length, imgp->args->begin_argv + offset, + imgp->args->endp - (imgp->args->begin_argv + length)); - /* copy the interpreter name */ - interp = imgp->interpreter_name; - while ((ihp < line_endp) && (*ihp != ' ') && (*ihp != '\t')) - *interp++ = *ihp++; - *interp = '\0'; + offset -= length; /* calculate actual adjustment */ + imgp->args->begin_envv += offset; + imgp->args->endp += offset; + imgp->args->stringspace -= offset; - /* Disallow a null interpreter filename */ - if (*imgp->interpreter_name == '\0') - return(ENOEXEC); + /* + * If there were no arguments then we've added one, otherwise + * decr argc remove old argv[0], incr argc for fname add, net 0 + */ + if (imgp->args->argc == 0) + imgp->args->argc = 1; - /* reset for another pass */ + /* + * Loop through the interpreter name yet again, copying as + * we go. + */ ihp = &image_header[2]; + offset = 0; + while (ihp < &image_header[MAXSHELLCMDLEN]) { + /* Skip whitespace */ + while ((*ihp == ' ' || *ihp == '\t')) { + ihp++; + continue; + } + + /* End of line? */ + if ((*ihp == '\n') || (*ihp == '#')) + break; - /* copy the interpreter name and arguments */ - while (ihp < line_endp) { - /* Skip over leading spaces */ - while ((*ihp == ' ') || (*ihp == '\t')) ihp++; - - if (ihp < line_endp) { - /* - * Copy to end of token. No need to watch stringspace - * because this is at the front of the string buffer - * and the maximum shell command length is tiny. - */ - while ((ihp < line_endp) && (*ihp != ' ') && (*ihp != '\t')) { - *imgp->stringp++ = *ihp++; - imgp->stringspace--; - } - - *imgp->stringp++ = 0; - imgp->stringspace--; - - imgp->argc++; + /* Found a token, copy it */ + while ((*ihp != ' ') && (*ihp != '\t') && + (*ihp != '\n') && (*ihp != '#')) { + imgp->args->begin_argv[offset++] = *ihp++; } + imgp->args->begin_argv[offset++] = '\0'; + imgp->args->argc++; } - imgp->argv0 = imgp->fname; + /* + * Finally, add the filename onto the end for the interpreter to + * use and copy the interpreter's name to imgp->interpreter_name + * for exec to use. + */ + error = copystr(imgp->args->fname, imgp->args->buf + offset, + imgp->args->stringspace, &length); + + if (error == 0) + error = copystr(imgp->args->begin_argv, imgp->interpreter_name, + MAXSHELLCMDLEN, &length); - return(0); + return (error); } /* diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 50fea85398b7..3998726c175c 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -79,8 +79,8 @@ MALLOC_DEFINE(M_PARGS, "proc-args", "Process arguments"); static int sysctl_kern_ps_strings(SYSCTL_HANDLER_ARGS); static int sysctl_kern_usrstack(SYSCTL_HANDLER_ARGS); static int sysctl_kern_stackprot(SYSCTL_HANDLER_ARGS); -static int do_execve(struct thread *td, char *fname, char **argv, - char **envv, struct mac *mac_p); +static int do_execve(struct thread *td, struct image_args *args, + struct mac *mac_p); /* XXX This should be vm_size_t. */ SYSCTL_PROC(_kern, KERN_PS_STRINGS, ps_strings, CTLTYPE_ULONG|CTLFLAG_RD, @@ -171,8 +171,18 @@ execve(td, uap) char **envv; } */ *uap; { + int error; + struct image_args args; + + error = exec_copyin_args(&args, uap->fname, UIO_USERSPACE, + uap->argv, uap->envv); + + if (error == 0) + error = kern_execve(td, &args, NULL); + + exec_free_args(&args); - return (kern_execve(td, uap->fname, uap->argv, uap->envv, NULL)); + return (error); } #ifndef _SYS_SYSPROTO_H_ @@ -197,21 +207,28 @@ __mac_execve(td, uap) struct mac *mac_p; } */ *uap; { - #ifdef MAC - return (kern_execve(td, uap->fname, uap->argv, uap->envv, - uap->mac_p)); + int error; + struct image_args args; + + error = exec_copyin_args(&args, uap->fname, UIO_USERSPACE, + uap->argv, uap->envv); + + if (error == 0) + error = kern_execve(td, &args, uap->mac_p); + + exec_free_args(&args); + + return (error); #else return (ENOSYS); #endif } int -kern_execve(td, fname, argv, envv, mac_p) +kern_execve(td, args, mac_p) struct thread *td; - char *fname; - char **argv; - char **envv; + struct image_args *args; struct mac *mac_p; { struct proc *p = td->td_proc; @@ -226,7 +243,7 @@ kern_execve(td, fname, argv, envv, mac_p) PROC_UNLOCK(p); } - error = do_execve(td, fname, argv, envv, mac_p); + error = do_execve(td, args, mac_p); if (p->p_flag & P_HADTHREADS) { PROC_LOCK(p); @@ -235,7 +252,7 @@ kern_execve(td, fname, argv, envv, mac_p) * force other threads to suicide. */ if (error == 0) - thread_single(SINGLE_EXIT); + thread_single(SINGLE_EXIT); else thread_single_end(); PROC_UNLOCK(p); @@ -251,11 +268,9 @@ kern_execve(td, fname, argv, envv, mac_p) * MPSAFE */ static int -do_execve(td, fname, argv, envv, mac_p) +do_execve(td, args, mac_p) struct thread *td; - char *fname; - char **argv; - char **envv; + struct image_args *args; struct mac *mac_p; { struct proc *p = td->td_proc; @@ -300,12 +315,8 @@ do_execve(td, fname, argv, envv, mac_p) * Initialize part of the common data */ imgp->proc = p; - imgp->userspace_argv = argv; - imgp->userspace_envv = envv; imgp->execlabel = NULL; imgp->attr = &attr; - imgp->argc = imgp->envc = 0; - imgp->argv0 = NULL; imgp->entry_addr = 0; imgp->vmspace_destroyed = 0; imgp->interpreted = 0; @@ -316,6 +327,7 @@ do_execve(td, fname, argv, envv, mac_p) imgp->firstpage = NULL; imgp->ps_strings = 0; imgp->auxarg_size = 0; + imgp->args = args; #ifdef MAC error = mac_execve_enter(imgp, mac_p); @@ -325,18 +337,6 @@ do_execve(td, fname, argv, envv, mac_p) } #endif - /* - * Allocate temporary demand zeroed space for argument and - * environment strings - */ - imgp->stringbase = (char *)kmem_alloc_wait(exec_map, ARG_MAX); - if (imgp->stringbase == NULL) { - error = ENOMEM; - mtx_lock(&Giant); - goto exec_fail; - } - imgp->stringp = imgp->stringbase; - imgp->stringspace = ARG_MAX; imgp->image_header = NULL; /* @@ -345,20 +345,16 @@ do_execve(td, fname, argv, envv, mac_p) */ ndp = &nd; NDINIT(ndp, LOOKUP, LOCKLEAF | FOLLOW | SAVENAME, - UIO_USERSPACE, fname, td); + UIO_SYSSPACE, args->fname, td); mtx_lock(&Giant); interpret: error = namei(ndp); - if (error) { - kmem_free_wakeup(exec_map, (vm_offset_t)imgp->stringbase, - ARG_MAX); + if (error) goto exec_fail; - } imgp->vp = ndp->ni_vp; - imgp->fname = fname; /* * Check file permissions (also 'opens' file) @@ -387,7 +383,7 @@ interpret: /* * If the current process has a special image activator it - * wants to try first, call it. For example, emulating shell + * wants to try first, call it. For example, emulating shell * scripts differently. */ error = -1; @@ -460,7 +456,7 @@ interpret: if (p->p_sysent->sv_fixup != NULL) (*p->p_sysent->sv_fixup)(&stack_base, imgp); else - suword(--stack_base, imgp->argc); + suword(--stack_base, imgp->args->argc); /* * For security and other reasons, the file descriptor table cannot @@ -473,7 +469,7 @@ interpret: */ newcred = crget(); euip = uifind(attr.va_uid); - i = imgp->endargs - imgp->stringbase; + i = imgp->args->begin_envv - imgp->args->begin_argv; if (ps_arg_cache_limit >= i + sizeof(struct pargs)) newargs = pargs_alloc(i); @@ -662,7 +658,7 @@ interpret: /* Cache arguments if they fit inside our allowance */ if (ps_arg_cache_limit >= i + sizeof(struct pargs)) { - bcopy(imgp->stringbase, newargs->ar_args, i); + bcopy(imgp->args->begin_argv, newargs->ar_args, i); p->p_args = newargs; newargs = NULL; } @@ -718,10 +714,6 @@ exec_fail_dealloc: vput(imgp->vp); } - if (imgp->stringbase != NULL) - kmem_free_wakeup(exec_map, (vm_offset_t)imgp->stringbase, - ARG_MAX); - if (imgp->object != NULL) vm_object_deallocate(imgp->object); @@ -739,7 +731,7 @@ exec_fail: PROC_LOCK(p); p->p_flag &= ~P_INEXEC; PROC_UNLOCK(p); - + if (imgp->vmspace_destroyed) { /* sorry, no more process anymore. exit gracefully */ #ifdef MAC @@ -925,73 +917,95 @@ exec_new_vmspace(imgp, sv) * address space into the temporary string buffer. */ int -exec_extract_strings(imgp) - struct image_params *imgp; +exec_copyin_args(struct image_args *args, char *fname, + enum uio_seg segflg, char **argv, char **envv) { - char **argv, **envv; - char *argp, *envp; - int error; - size_t length; + char *argp, *envp; + int error; + size_t length; + + error = 0; + bzero(args, sizeof(*args)); + if (argv == NULL) + return (EFAULT); /* - * extract arguments first + * Allocate temporary demand zeroed space for argument and + * environment strings */ + args->buf = (char *) kmem_alloc_wait(exec_map, PATH_MAX + ARG_MAX); + if (args->buf == NULL) + return (ENOMEM); + args->begin_argv = args->buf; + args->endp = args->begin_argv; + args->stringspace = ARG_MAX; + + args->fname = args->buf + ARG_MAX; - argv = imgp->userspace_argv; + /* + * Copy the file name. + */ + error = (segflg == UIO_SYSSPACE) ? + copystr(fname, args->fname, PATH_MAX, &length) : + copyinstr(fname, args->fname, PATH_MAX, &length); + if (error != 0) { + if (error == ENAMETOOLONG) + return (E2BIG); + return (error); + } - if (argv) { - argp = (caddr_t)(intptr_t)fuword(argv); - if (argp == (caddr_t)-1) + /* + * extract arguments first + */ + while ((argp = (caddr_t) (intptr_t) fuword(argv++))) { + if (argp == (caddr_t) -1) return (EFAULT); - if (argp) - argv++; - if (imgp->argv0) - argp = imgp->argv0; - if (argp) { - do { - if (argp == (caddr_t)-1) - return (EFAULT); - if ((error = copyinstr(argp, imgp->stringp, - imgp->stringspace, &length))) { - if (error == ENAMETOOLONG) - return (E2BIG); - return (error); - } - imgp->stringspace -= length; - imgp->stringp += length; - imgp->argc++; - } while ((argp = (caddr_t)(intptr_t)fuword(argv++))); + if ((error = copyinstr(argp, args->endp, + args->stringspace, &length))) { + if (error == ENAMETOOLONG) + return (E2BIG); + return (error); } - } else - return (EFAULT); + args->stringspace -= length; + args->endp += length; + args->argc++; + } - imgp->endargs = imgp->stringp; + args->begin_envv = args->endp; /* * extract environment strings */ - - envv = imgp->userspace_envv; - if (envv) { while ((envp = (caddr_t)(intptr_t)fuword(envv++))) { if (envp == (caddr_t)-1) return (EFAULT); - if ((error = copyinstr(envp, imgp->stringp, - imgp->stringspace, &length))) { + if ((error = copyinstr(envp, args->endp, + args->stringspace, &length))) { if (error == ENAMETOOLONG) return (E2BIG); return (error); } - imgp->stringspace -= length; - imgp->stringp += length; - imgp->envc++; + args->stringspace -= length; + args->endp += length; + args->envc++; } } return (0); } +void +exec_free_args(struct image_args *args) +{ + + if (args->buf) { + kmem_free_wakeup(exec_map, + (vm_offset_t)args->buf, PATH_MAX + ARG_MAX); + args->buf = NULL; + } +} + /* * Copy strings out to the new process address space, constructing * new arg and env vector tables. Return a pointer to the base @@ -1019,7 +1033,7 @@ exec_copyout_strings(imgp) if (p->p_sysent->sv_szsigcode != NULL) szsigcode = *(p->p_sysent->sv_szsigcode); destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE - - roundup((ARG_MAX - imgp->stringspace), sizeof(char *)); + roundup((ARG_MAX - imgp->args->stringspace), sizeof(char *)); /* * install sigcode @@ -1044,30 +1058,32 @@ exec_copyout_strings(imgp) * the arg and env vector sets,and imgp->auxarg_size is room * for argument of Runtime loader. */ - vectp = (char **)(destp - (imgp->argc + imgp->envc + 2 + - imgp->auxarg_size) * sizeof(char *)); + vectp = (char **)(destp - (imgp->args->argc + + imgp->args->envc + 2 + imgp->auxarg_size) * + sizeof(char *)); - } else + } else { /* * The '+ 2' is for the null pointers at the end of each of * the arg and env vector sets */ - vectp = (char **)(destp - (imgp->argc + imgp->envc + 2) * + vectp = (char **)(destp - (imgp->args->argc + imgp->args->envc + 2) * sizeof(char *)); + } /* * vectp also becomes our initial stack base */ stack_base = (register_t *)vectp; - stringp = imgp->stringbase; - argc = imgp->argc; - envc = imgp->envc; + stringp = imgp->args->begin_argv; + argc = imgp->args->argc; + envc = imgp->args->envc; /* * Copy out strings - arguments and environment. */ - copyout(stringp, destp, ARG_MAX - imgp->stringspace); + copyout(stringp, destp, ARG_MAX - imgp->args->stringspace); /* * Fill in "ps_strings" struct for ps, w, etc. diff --git a/sys/kern/kern_kse.c b/sys/kern/kern_kse.c index d0e03ecb9df7..4e648f541850 100644 --- a/sys/kern/kern_kse.c +++ b/sys/kern/kern_kse.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> +#include <sys/imgact.h> #include <sys/lock.h> #include <sys/mutex.h> #include <sys/proc.h> @@ -176,6 +177,7 @@ int kse_thr_interrupt(struct thread *td, struct kse_thr_interrupt_args *uap) { struct kse_execve_args args; + struct image_args iargs; struct proc *p; struct thread *td2; struct kse_upcall *ku; @@ -261,7 +263,11 @@ kse_thr_interrupt(struct thread *td, struct kse_thr_interrupt_args *uap) error = copyin((void *)uap->data, &args, sizeof(args)); if (error) return (error); - error = kern_execve(td, args.path, args.argv, args.envp, NULL); + error = exec_copyin_args(&iargs, args.path, UIO_USERSPACE, + args.argv, args.envp); + if (error == 0) + error = kern_execve(td, &iargs, NULL); + exec_free_args(&iargs); if (error == 0) { PROC_LOCK(p); SIGSETOR(td->td_siglist, args.sigpend); diff --git a/sys/modules/Makefile b/sys/modules/Makefile index 720fd2295f7b..af12bb03173c 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -175,6 +175,7 @@ SUBDIR= ${_3dfx} \ procfs \ pseudofs \ ${_pst} \ + ${_radio} \ ${_random} \ ${_ray} \ rc \ @@ -326,6 +327,7 @@ _oltr= oltr _pccard= pccard _pcfclock= pcfclock _pecoff= pecoff +#_radio= radio _pst= pst _ray= ray _safe= safe diff --git a/sys/sys/imgact.h b/sys/sys/imgact.h index 142d0297ed4b..df79dfbd29ca 100644 --- a/sys/sys/imgact.h +++ b/sys/sys/imgact.h @@ -32,32 +32,37 @@ #ifndef _SYS_IMGACT_H_ #define _SYS_IMGACT_H_ +#include <sys/uio.h> + #define MAXSHELLCMDLEN 128 +struct image_args { + char *buf; /* pointer to string buffer */ + char *begin_argv; /* beginning of argv in buf */ + char *begin_envv; /* beginning of envv in buf */ + char *endp; /* current `end' pointer of arg & env strings */ + char *fname; /* pointer to filename of executable (system space) */ + int stringspace; /* space left in arg & env buffer */ + int argc; /* count of argument strings */ + int envc; /* count of environment strings */ +}; + struct image_params { struct proc *proc; /* our process struct */ - char **userspace_argv; /* system call argument */ - char **userspace_envv; /* system call argument */ struct label *execlabel; /* optional exec label */ struct vnode *vp; /* pointer to vnode of file to exec */ struct vm_object *object; /* The vm object for this vp */ struct vattr *attr; /* attributes of file */ const char *image_header; /* head of file to exec */ - char *stringbase; /* base address of tmp string storage */ - char *stringp; /* current 'end' pointer of tmp strings */ - char *endargs; /* end of argv vector */ - int stringspace; /* space left in tmp string storage area */ - int argc, envc; /* count of argument and environment strings */ - char *argv0; /* Replacement for argv[0] when interpreting */ unsigned long entry_addr; /* entry address of target executable */ char vmspace_destroyed; /* flag - we've blown away original vm space */ char interpreted; /* flag - this executable is interpreted */ char interpreter_name[MAXSHELLCMDLEN]; /* name of the interpreter */ void *auxargs; /* ELF Auxinfo structure pointer */ struct sf_buf *firstpage; /* first page that we mapped */ - char *fname; /* pointer to filename of executable (user space) */ unsigned long ps_strings; /* PS_STRINGS for BSD/OS binaries */ size_t auxarg_size; + struct image_args *args; /* system call arguments */ }; #ifdef _KERNEL @@ -66,10 +71,12 @@ struct thread; int exec_check_permissions(struct image_params *); register_t *exec_copyout_strings(struct image_params *); -int exec_extract_strings(struct image_params *); int exec_new_vmspace(struct image_params *, struct sysentvec *); void exec_setregs(struct thread *, u_long, u_long, u_long); int exec_shell_imgact(struct image_params *); +int exec_copyin_args(struct image_args *, char *, enum uio_seg, + char **, char **); +void exec_free_args(struct image_args *); #endif #endif /* !_SYS_IMGACT_H_ */ diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h index d161c7a06427..b7bb0f1ab28c 100644 --- a/sys/sys/syscallsubr.h +++ b/sys/sys/syscallsubr.h @@ -40,6 +40,7 @@ struct rusage; struct sockaddr; struct itimerval; struct msqid_ds; +struct image_args; int kern___getcwd(struct thread *td, u_char *buf, enum uio_seg bufseg, u_int buflen); @@ -52,7 +53,7 @@ int kern_chmod(struct thread *td, char *path, enum uio_seg pathseg, int kern_chown(struct thread *td, char *path, enum uio_seg pathseg, int uid, int gid); int kern_connect(struct thread *td, int fd, struct sockaddr *sa); -int kern_execve(struct thread *td, char *fname, char **argv, char **envv, +int kern_execve(struct thread *td, struct image_args *args, struct mac *mac_p); int kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg); int kern_futimes(struct thread *td, int fd, struct timeval *tptr, |