Ping?
On Sat, Dec 12, 2015 at 8:38 PM, Maxim Pugachev <pugachev...@gmail.com> wrote:
> 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);