Hi, This patch removes copypasted code that prepares args and env in exec system call.
Index: sys/kern/kern_exec.c =================================================================== RCS file: /cvs/src/sys/kern/kern_exec.c,v retrieving revision 1.173 diff -u -p -r1.173 kern_exec.c --- sys/kern/kern_exec.c 5 Dec 2015 10:11:53 -0000 1.173 +++ sys/kern/kern_exec.c 12 Dec 2015 17:34:43 -0000 @@ -77,6 +77,12 @@ const struct kmem_va_mode kv_exec = { .kv_map = &exec_map }; +struct argcontext +{ + char *buffer; + char *bptr; +}; + /* * Map the shared signal code. */ @@ -231,6 +237,58 @@ bad1: return (error); } +void +copy_fake_args(struct exec_package *pack, struct argcontext *argctx, + long *count) +{ + char **fake_args_vec = pack->ep_fa; + + while (*fake_args_vec != NULL) { + char *arg = *fake_args_vec; + + while (*arg) + *argctx->bptr++ = *arg++; + + *argctx->bptr++ = '\0'; + + free(*fake_args_vec, M_EXEC, 0); + + fake_args_vec++; + (*count)++; + } + + free(pack->ep_fa, M_EXEC, 0); + pack->ep_flags &= ~EXEC_HASARGL; +} + +int +copy_strings(char * const *src, struct argcontext *argctx, long *count) +{ + int error; + size_t len; + size_t maxlen = argctx->buffer + ARG_MAX - argctx->bptr; + char *sp; + + while (1) { + if ((error = copyin(src, &sp, sizeof(sp))) != 0) + return error; + if (!sp) + break; + if ((error = copyinstr(sp, argctx->bptr, maxlen, &len)) != 0) { + if (error == ENAMETOOLONG) + error = E2BIG; + return error; + } + + maxlen -= len; + argctx->bptr += len; + src++; + (*count)++; + } + + return 0; +} + /* * exec system call */ @@ -242,13 +300,13 @@ sys_execve(struct proc *p, void *v, regi syscallarg(char *const *) argp; syscallarg(char *const *) envp; } */ *uap = v; + struct argcontext argctx; int error; struct exec_package pack; struct nameidata nid; struct vattr attr; struct ucred *cred = p->p_ucred; - char *argp; - char * const *cpp, *dp, *sp; + char * const *cpp; #ifdef KTRACE char *env_start; #endif @@ -261,7 +319,6 @@ sys_execve(struct proc *p, void *v, regi char *stack; struct ps_strings arginfo; struct vmspace *vm = pr->ps_vmspace; - char **tmpfap; extern struct emul emul_native; #if NSYSTRACE > 0 int wassugid = ISSET(pr->ps_flags, PS_SUGID | PS_SUGIDEXEC); @@ -317,38 +374,23 @@ sys_execve(struct proc *p, void *v, regi pack.ep_flags = 0; /* see if we can run it. */ - if ((error = check_exec(p, &pack)) != 0) { + if ((error = check_exec(p, &pack)) != 0) goto freehdr; - } /* XXX -- THE FOLLOWING SECTION NEEDS MAJOR CLEANUP */ - + /* allocate an argument buffer */ - argp = km_alloc(NCARGS, &kv_exec, &kp_pageable, &kd_waitok); + argctx.buffer = km_alloc(NCARGS, &kv_exec, &kp_pageable, &kd_waitok); #ifdef DIAGNOSTIC - if (argp == NULL) - panic("execve: argp == NULL"); + if (argctx.buffer == NULL) + panic("execve: argctx.buffer == NULL"); #endif - dp = argp; + argctx.bptr = argctx.buffer; argc = 0; /* copy the fake args list, if there's one, freeing it as we go */ - if (pack.ep_flags & EXEC_HASARGL) { - tmpfap = pack.ep_fa; - while (*tmpfap != NULL) { - char *cp; - - cp = *tmpfap; - while (*cp) - *dp++ = *cp++; - *dp++ = '\0'; - - free(*tmpfap, M_EXEC, 0); - tmpfap++; argc++; - } - free(pack.ep_fa, M_EXEC, 0); - pack.ep_flags &= ~EXEC_HASARGL; - } + if (pack.ep_flags & EXEC_HASARGL) + copy_fake_args(&pack, &argctx, &argc); /* Now get argv & environment */ if (!(cpp = SCARG(uap, argp))) { @@ -359,21 +401,9 @@ sys_execve(struct proc *p, void *v, regi if (pack.ep_flags & EXEC_SKIPARG) cpp++; - while (1) { - len = argp + ARG_MAX - dp; - if ((error = copyin(cpp, &sp, sizeof(sp))) != 0) - goto bad; - if (!sp) - break; - if ((error = copyinstr(sp, dp, len, &len)) != 0) { - if (error == ENAMETOOLONG) - error = E2BIG; - goto bad; - } - dp += len; - cpp++; - argc++; - } + /* copy args */ + if (copy_strings(cpp, &argctx, &argc) != 0) + goto bad; /* must have at least one argument */ if (argc == 0) { @@ -382,39 +412,31 @@ sys_execve(struct proc *p, void *v, regi } #ifdef KTRACE - if (KTRPOINT(p, KTR_EXECARGS)) - ktrexec(p, KTR_EXECARGS, argp, dp - argp); + if (KTRPOINT(p, KTR_EXECARGS)) { + ktrexec(p, KTR_EXECARGS, argctx.buffer, + argctx.bptr - argctx.buffer); + } #endif envc = 0; /* environment does not need to be there */ if ((cpp = SCARG(uap, envp)) != NULL ) { #ifdef KTRACE - env_start = dp; + env_start = argctx.bptr; #endif - while (1) { - len = argp + ARG_MAX - dp; - if ((error = copyin(cpp, &sp, sizeof(sp))) != 0) - goto bad; - if (!sp) - break; - if ((error = copyinstr(sp, dp, len, &len)) != 0) { - if (error == ENAMETOOLONG) - error = E2BIG; - goto bad; - } - dp += len; - cpp++; - envc++; - } - + if (copy_strings(cpp, &argctx, &envc) != 0) + goto bad; #ifdef KTRACE - if (KTRPOINT(p, KTR_EXECENV)) - ktrexec(p, KTR_EXECENV, env_start, dp - env_start); + if (KTRPOINT(p, KTR_EXECENV)) { + ktrexec(p, KTR_EXECENV, env_start, + argctx.bptr - env_start); + } #endif } - dp = (char *)(((long)dp + _STACKALIGNBYTES) & ~_STACKALIGNBYTES); + argctx.bptr = + (char *)(((long)argctx.bptr + _STACKALIGNBYTES) & + ~_STACKALIGNBYTES); sgap = STACKGAPLEN; @@ -430,7 +452,8 @@ sys_execve(struct proc *p, void *v, regi /* Now check if args & environ fit into new stack */ len = ((argc + envc + 2 + pack.ep_emul->e_arglen) * sizeof(char *) + - sizeof(long) + dp + sgap + sizeof(struct ps_strings)) - argp; + sizeof(long) + argctx.bptr + sgap + sizeof(struct ps_strings)) - + argctx.buffer; len = (len + _STACKALIGNBYTES) &~ _STACKALIGNBYTES; @@ -505,7 +528,7 @@ sys_execve(struct proc *p, void *v, regi stack = (char *)(vm->vm_minsaddr - len); #endif /* Now copy argc, args & environ to new stack */ - if (!(*pack.ep_emul->e_copyargs)(&pack, &arginfo, stack, argp)) + if (!(*pack.ep_emul->e_copyargs)(&pack, &arginfo, stack, argctx.buffer)) goto exec_abort; /* copy out the process's ps_strings structure */ @@ -672,7 +695,7 @@ sys_execve(struct proc *p, void *v, regi timespecclear(&p->p_tu.tu_runtime); p->p_tu.tu_uticks = p->p_tu.tu_sticks = p->p_tu.tu_iticks = 0; - km_free(argp, NCARGS, &kv_exec, &kp_pageable); + km_free(argctx.buffer, NCARGS, &kv_exec, &kp_pageable); pool_put(&namei_pool, nid.ni_cnd.cn_pnbuf); vn_close(pack.ep_vp, FREAD, cred, p); @@ -777,7 +800,7 @@ bad: /* close and put the exec'd file */ vn_close(pack.ep_vp, FREAD, cred, p); pool_put(&namei_pool, nid.ni_cnd.cn_pnbuf); - km_free(argp, NCARGS, &kv_exec, &kp_pageable); + km_free(argctx.buffer, NCARGS, &kv_exec, &kp_pageable); freehdr: free(pack.ep_hdr, M_EXEC, pack.ep_hdrlen); @@ -806,7 +829,7 @@ exec_abort: free(pack.ep_emul_arg, M_TEMP, pack.ep_emul_argsize); pool_put(&namei_pool, nid.ni_cnd.cn_pnbuf); vn_close(pack.ep_vp, FREAD, cred, p); - km_free(argp, NCARGS, &kv_exec, &kp_pageable); + km_free(argctx.buffer, NCARGS, &kv_exec, &kp_pageable); free_pack_abort: free(pack.ep_hdr, M_EXEC, pack.ep_hdrlen);