Index: sys/compat/freebsd32/freebsd32_misc.c =================================================================== --- sys/compat/freebsd32/freebsd32_misc.c +++ sys/compat/freebsd32/freebsd32_misc.c @@ -337,7 +337,6 @@ { char *argp, *envp; u_int32_t *p32, arg; - size_t length; int error; bzero(args, sizeof(*args)); @@ -355,19 +354,9 @@ /* * Copy the file name. */ - if (fname != NULL) { - args->fname = args->buf; - error = (segflg == UIO_SYSSPACE) ? - copystr(fname, args->fname, PATH_MAX, &length) : - copyinstr(fname, args->fname, PATH_MAX, &length); - if (error != 0) - goto err_exit; - } else - length = 0; - - args->begin_argv = args->buf + length; - args->endp = args->begin_argv; - args->stringspace = ARG_MAX; + error = exec_args_add_fname(args, fname, segflg); + if (error != 0) + goto err_exit; /* * extract arguments first @@ -380,15 +369,10 @@ if (arg == 0) break; argp = PTRIN(arg); - error = copyinstr(argp, args->endp, args->stringspace, &length); - if (error) { - if (error == ENAMETOOLONG) - error = E2BIG; + error = exec_args_add_arg_str(args, (void *)argp, + UIO_USERSPACE); + if (error != 0) goto err_exit; - } - args->stringspace -= length; - args->endp += length; - args->argc++; } args->begin_envv = args->endp; @@ -405,16 +389,10 @@ if (arg == 0) break; envp = PTRIN(arg); - error = copyinstr(envp, args->endp, args->stringspace, - &length); - if (error) { - if (error == ENAMETOOLONG) - error = E2BIG; + error = exec_args_add_env_str(args, (void *)envp, + UIO_USERSPACE); + if (error != 0) goto err_exit; - } - args->stringspace -= length; - args->endp += length; - args->envc++; } } Index: sys/kern/kern_exec.c =================================================================== --- sys/kern/kern_exec.c +++ sys/kern/kern_exec.c @@ -1170,7 +1170,6 @@ { u_long argp, envp; int error; - size_t length; bzero(args, sizeof(*args)); if (argv == NULL) @@ -1187,19 +1186,9 @@ /* * Copy the file name. */ - if (fname != NULL) { - args->fname = args->buf; - error = (segflg == UIO_SYSSPACE) ? - copystr(fname, args->fname, PATH_MAX, &length) : - copyinstr(fname, args->fname, PATH_MAX, &length); - if (error != 0) - goto err_exit; - } else - length = 0; - - args->begin_argv = args->buf + length; - args->endp = args->begin_argv; - args->stringspace = ARG_MAX; + error = exec_args_add_fname(args, fname, segflg); + if (error != 0) + goto err_exit; /* * extract arguments first @@ -1212,16 +1201,10 @@ } if (argp == 0) break; - error = copyinstr((void *)(uintptr_t)argp, args->endp, - args->stringspace, &length); - if (error != 0) { - if (error == ENAMETOOLONG) - error = E2BIG; + error = exec_args_add_arg_str(args, (void *)argp, + UIO_USERSPACE); + if (error != 0) goto err_exit; - } - args->stringspace -= length; - args->endp += length; - args->argc++; } args->begin_envv = args->endp; @@ -1238,16 +1221,10 @@ } if (envp == 0) break; - error = copyinstr((void *)(uintptr_t)envp, - args->endp, args->stringspace, &length); - if (error != 0) { - if (error == ENAMETOOLONG) - error = E2BIG; + error = exec_args_add_env_str(args, (void *)envp, + UIO_USERSPACE); + if (error != 0) goto err_exit; - } - args->stringspace -= length; - args->endp += length; - args->envc++; } } @@ -1459,6 +1436,89 @@ fdescfree_remapped(args->fdp); } +/* + * A set to functions to fill struct image args. + * + * NOTE: exec_args_add_fname() must be called (possiably with a NULL + * fname) before any _arg_ or _env_ functions. All _arg_ calls should be + * made before any _env_ calls. + * + * exec_args_add_fname() - install path to be executed + * exec_args_add_arg_str() - append an argument string + * exec_args_add_env_str() - append an env string + */ +int +exec_args_add_fname(struct image_args *args, char *fname, + enum uio_seg segflg) +{ + int error; + size_t length; + + KASSERT(args->fname == NULL, ("fname already appended")); + KASSERT(args->endp == NULL, ("already appending to args")); + + if (fname != NULL) { + args->fname = args->buf; + error = (segflg == UIO_SYSSPACE) ? + copystr(fname, args->fname, PATH_MAX, &length) : + copyinstr(fname, args->fname, PATH_MAX, &length); + if (error != 0) + return (error == ENAMETOOLONG ? E2BIG : error); + } else + length = 0; + + /* Set up for _arg_*()/_env_*() */ + args->endp = args->buf + length; + /* begin_argv and begin_envv must be set and updated */ + args->begin_argv = args->begin_envv = args->endp; + /* Actually (exec_map_entry_size - length) which is >= ARG_MAX */ + args->stringspace = ARG_MAX; + + return (0); +} + +int +exec_args_add_arg_str(struct image_args *args, char *argp, enum uio_seg segflg) +{ + int error; + size_t length; + + KASSERT(args->begin_argv != NULL, ("begin_argp not initialzed")); + KASSERT(args->begin_envv == args->endp, ("appending args after env")); + + error = (segflg == UIO_SYSSPACE) ? + copystr(argp, args->endp, args->stringspace, &length) : + copyinstr(argp, args->endp, args->stringspace, &length); + if (error != 0) + return (error == ENAMETOOLONG ? E2BIG : error); + args->stringspace -= length; + args->endp += length; + args->begin_envv += length; + args->argc++; + + return (0); +} + +int +exec_args_add_env_str(struct image_args *args, char *envp, enum uio_seg segflg) +{ + int error; + size_t length; + + KASSERT(args->begin_envv != NULL, ("begin_envv not initialzed")); + + error = (segflg == UIO_SYSSPACE) ? + copystr(envp, args->endp, args->stringspace, &length) : + copyinstr(envp, args->endp, args->stringspace, &length); + if (error != 0) + return (error == ENAMETOOLONG ? E2BIG : error); + args->stringspace -= length; + args->endp += length; + args->envc++; + + return (0); +} + /* * Copy strings out to the new process address space, constructing new arg * and env vector tables. Return a pointer to the base so that it can be used Index: sys/sys/imgact.h =================================================================== --- sys/sys/imgact.h +++ sys/sys/imgact.h @@ -96,6 +96,12 @@ struct vmspace; int exec_alloc_args(struct image_args *); +int exec_args_add_arg_str(struct image_args *args, char *argp, + enum uio_seg segflg); +int exec_args_add_env_str(struct image_args *args, char *envp, + enum uio_seg segflg); +int exec_args_add_fname(struct image_args *args, char *fname, + enum uio_seg segflg); int exec_check_permissions(struct image_params *); register_t *exec_copyout_strings(struct image_params *); void exec_free_args(struct image_args *);