Index: sys/amd64/linux/linux_sysvec.c =================================================================== --- sys/amd64/linux/linux_sysvec.c +++ sys/amd64/linux/linux_sysvec.c @@ -96,7 +96,8 @@ SET_DECLARE(linux_ioctl_handler_set, struct linux_ioctl_handler); -static register_t * linux_copyout_strings(struct image_params *imgp); +static int linux_copyout_strings(struct image_params *imgp, + register_t **stack_base); static int linux_fixup_elf(register_t **stack_base, struct image_params *iparams); static bool linux_trans_osrel(const Elf_Note *note, int32_t *osrel); @@ -222,14 +223,14 @@ set_pcb_flags(td->td_pcb, PCB_FULL_IRET); } -static void +static int linux_copyout_auxargs(struct image_params *imgp, u_long *base) { Elf_Auxargs *args; Elf_Auxinfo *argarray, *pos; u_long auxlen; struct proc *p; - int issetugid; + int error, issetugid; p = imgp->proc; args = (Elf64_Auxargs *)imgp->auxargs; @@ -267,8 +268,9 @@ auxlen = sizeof(*argarray) * (pos - argarray); *base -= auxlen; - copyout(argarray, (void *)*base, auxlen); + error = copyout(argarray, (void *)*base, auxlen); free(argarray, M_TEMP); + return (error); } static int @@ -290,13 +292,12 @@ * and env vector tables. Return a pointer to the base so that it can be used * as the initial stack pointer. */ -static register_t * -linux_copyout_strings(struct image_params *imgp) +static int +linux_copyout_strings(struct image_params *imgp, register_t **stack_base) { - int argc, envc; + int argc, envc, error; char **vectp; char *stringp, *destp; - register_t *stack_base; struct ps_strings *arginfo; char canary[LINUX_AT_RANDOM_LEN]; size_t execpath_len; @@ -317,7 +318,10 @@ if (execpath_len != 0) { imgp->execpathp = (uintptr_t)arginfo - execpath_len; - copyout(imgp->execpath, (void *)imgp->execpathp, execpath_len); + error = copyout(imgp->execpath, (void *)imgp->execpathp, + execpath_len); + if (error) + return (error); } /* Prepare the canary for SSP. */ @@ -325,7 +329,9 @@ imgp->canary = (uintptr_t)arginfo - roundup(execpath_len, sizeof(char *)) - roundup(sizeof(canary), sizeof(char *)); - copyout(canary, (void *)imgp->canary, sizeof(canary)); + error = copyout(canary, (void *)imgp->canary, sizeof(canary)); + if (error) + return (error); vectp = (char **)destp; @@ -335,8 +341,12 @@ */ vectp = (char **)((((uintptr_t)vectp + 8) & ~0xF) - 8); - if (imgp->auxargs) - imgp->sysent->sv_copyout_auxargs(imgp, (u_long *)&vectp); + if (imgp->auxargs) { + error = imgp->sysent->sv_copyout_auxargs(imgp, + (u_long *)&vectp); + if (error) + return (error); + } /* * Allocate room for the argv[] and env vectors including the @@ -345,44 +355,53 @@ vectp -= imgp->args->argc + 1 + imgp->args->envc + 1; /* vectp also becomes our initial stack base. */ - stack_base = (register_t *)vectp; + *stack_base = (register_t *)vectp; 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->args->stringspace); + error = copyout(stringp, destp, ARG_MAX - imgp->args->stringspace); + if (error) + return (error); /* Fill in "ps_strings" struct for ps, w, etc. */ - suword(&arginfo->ps_argvstr, (long)(intptr_t)vectp); - suword(&arginfo->ps_nargvstr, argc); + if (suword(&arginfo->ps_argvstr, (long)(intptr_t)vectp) != 0 || + suword(&arginfo->ps_nargvstr, argc) != 0) + return (EFAULT); /* Fill in argument portion of vector table. */ for (; argc > 0; --argc) { - suword(vectp++, (long)(intptr_t)destp); + if (suword(vectp++, (long)(intptr_t)destp) != 0) + return (EFAULT); while (*stringp++ != 0) destp++; destp++; } /* A null vector table pointer separates the argp's from the envp's. */ - suword(vectp++, 0); + if (suword(vectp++, 0) != 0) + return (EFAULT); - suword(&arginfo->ps_envstr, (long)(intptr_t)vectp); - suword(&arginfo->ps_nenvstr, envc); + if (suword(&arginfo->ps_envstr, (long)(intptr_t)vectp) != 0 || + suword(&arginfo->ps_nenvstr, envc) != 0) + return (EFAULT); /* Fill in environment portion of vector table. */ for (; envc > 0; --envc) { - suword(vectp++, (long)(intptr_t)destp); + if (suword(vectp++, (long)(intptr_t)destp) != 0) + return (EFAULT); while (*stringp++ != 0) destp++; destp++; } /* The end of the vector table is a null pointer. */ - suword(vectp, 0); - return (stack_base); + if (suword(vectp, 0) != 0) + return (EFAULT); + + return (0); } /* Index: sys/amd64/linux32/linux32_sysvec.c =================================================================== --- sys/amd64/linux32/linux32_sysvec.c +++ sys/amd64/linux32/linux32_sysvec.c @@ -103,7 +103,8 @@ static int linux_fixup_elf(register_t **stack_base, struct image_params *iparams); -static register_t *linux_copyout_strings(struct image_params *imgp); +static int linux_copyout_strings(struct image_params *imgp, + register_t **stack_base); static void linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask); static void linux_exec_setregs(struct thread *td, struct image_params *imgp, u_long stack); @@ -185,13 +186,13 @@ } } -static void +static int linux_copyout_auxargs(struct image_params *imgp, u_long *base) { Elf32_Auxargs *args; Elf32_Auxinfo *argarray, *pos; u_long auxlen; - int issetugid; + int error, issetugid; args = (Elf32_Auxargs *)imgp->auxargs; argarray = pos = malloc(LINUX_AT_COUNT * sizeof(*pos), M_TEMP, @@ -239,8 +240,9 @@ auxlen = sizeof(*argarray) * (pos - argarray); *base -= auxlen; - copyout(argarray, (void *)*base, auxlen); + error = copyout(argarray, (void *)*base, auxlen); free(argarray, M_TEMP); + return (error); } static int @@ -718,13 +720,12 @@ /* * XXX copied from ia32_sysvec.c. */ -static register_t * -linux_copyout_strings(struct image_params *imgp) +static int +linux_copyout_strings(struct image_params *imgp, register_t **stack_base) { - int argc, envc; + int argc, envc, error; u_int32_t *vectp; char *stringp, *destp; - u_int32_t *stack_base; struct linux32_ps_strings *arginfo; char canary[LINUX_AT_RANDOM_LEN]; size_t execpath_len; @@ -743,7 +744,10 @@ if (execpath_len != 0) { imgp->execpathp = (uintptr_t)arginfo - execpath_len; - copyout(imgp->execpath, (void *)imgp->execpathp, execpath_len); + error = copyout(imgp->execpath, (void *)imgp->execpathp, + execpath_len); + if (error) + return (error); } /* Prepare the canary for SSP. */ @@ -751,11 +755,17 @@ imgp->canary = (uintptr_t)arginfo - roundup(execpath_len, sizeof(char *)) - roundup(sizeof(canary), sizeof(char *)); - copyout(canary, (void *)imgp->canary, sizeof(canary)); + error = copyout(canary, (void *)imgp->canary, sizeof(canary)); + if (error) + return (error); vectp = (uint32_t *)destp; - if (imgp->auxargs) - imgp->sysent->sv_copyout_auxargs(imgp, (u_long *)&vectp); + if (imgp->auxargs) { + error = imgp->sysent->sv_copyout_auxargs(imgp, + (u_long *)&vectp); + if (error) + return (error); + } /* * Allocate room for the argv[] and env vectors including the @@ -764,44 +774,52 @@ vectp -= imgp->args->argc + 1 + imgp->args->envc + 1; /* vectp also becomes our initial stack base. */ - stack_base = vectp; + *stack_base = (register_t *)vectp; 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->args->stringspace); + error = copyout(stringp, destp, ARG_MAX - imgp->args->stringspace); + if (error) + return (error); /* Fill in "ps_strings" struct for ps, w, etc. */ - suword32(&arginfo->ps_argvstr, (uint32_t)(intptr_t)vectp); - suword32(&arginfo->ps_nargvstr, argc); + if (suword32(&arginfo->ps_argvstr, (uint32_t)(intptr_t)vectp) != 0 || + suword32(&arginfo->ps_nargvstr, argc) != 0) + return (EFAULT); /* Fill in argument portion of vector table. */ for (; argc > 0; --argc) { - suword32(vectp++, (uint32_t)(intptr_t)destp); + if (suword32(vectp++, (uint32_t)(intptr_t)destp) != 0) + return (EFAULT); while (*stringp++ != 0) destp++; destp++; } /* A null vector table pointer separates the argp's from the envp's. */ - suword32(vectp++, 0); + if (suword32(vectp++, 0) != 0) + return (EFAULT); - suword32(&arginfo->ps_envstr, (uint32_t)(intptr_t)vectp); - suword32(&arginfo->ps_nenvstr, envc); + if (suword32(&arginfo->ps_envstr, (uint32_t)(intptr_t)vectp) != 0 || + suword32(&arginfo->ps_nenvstr, envc) != 0) + return (EFAULT); /* Fill in environment portion of vector table. */ for (; envc > 0; --envc) { - suword32(vectp++, (uint32_t)(intptr_t)destp); + if (suword32(vectp++, (uint32_t)(intptr_t)destp) != 0) + return (EFAULT); while (*stringp++ != 0) destp++; destp++; } /* The end of the vector table is a null pointer. */ - suword32(vectp, 0); + if (suword32(vectp, 0) != 0) + return (EFAULT); - return ((register_t *)stack_base); + return (0); } static SYSCTL_NODE(_compat, OID_AUTO, linux32, CTLFLAG_RW, 0, Index: sys/arm64/linux/linux_sysvec.c =================================================================== --- sys/arm64/linux/linux_sysvec.c +++ sys/arm64/linux/linux_sysvec.c @@ -69,7 +69,8 @@ SET_DECLARE(linux_ioctl_handler_set, struct linux_ioctl_handler); -static register_t *linux_copyout_strings(struct image_params *imgp); +static int linux_copyout_strings(struct image_params *imgp, + register_t **stack_base); static int linux_elf_fixup(register_t **stack_base, struct image_params *iparams); static bool linux_trans_osrel(const Elf_Note *note, int32_t *osrel); @@ -141,14 +142,14 @@ cpu_set_syscall_retval(td, error); } -static void +static int linux_copyout_auxargs(struct image_params *imgp, u_long *base) { Elf_Auxargs *args; Elf_Auxinfo *argarray, *pos; u_long auxlen; struct proc *p; - int issetugid; + int error, issetugid; LIN_SDT_PROBE0(sysvec, linux_copyout_auxargs, todo); p = imgp->proc; @@ -191,8 +192,9 @@ auxlen = sizeof(*argarray) * (pos - argarray); *base -= auxlen; - copyout(argarray, (void *)*base, auxlen); + error = copyout(argarray, (void *)*base, auxlen); free(argarray, M_TEMP); + return (error); } static int @@ -210,17 +212,16 @@ * as the initial stack pointer. * LINUXTODO: deduplicate against other linuxulator archs */ -static register_t * -linux_copyout_strings(struct image_params *imgp) +static int +linux_copyout_strings(struct image_params *imgp, register_t **stack_base) { char **vectp; char *stringp, *destp; - register_t *stack_base; struct ps_strings *arginfo; char canary[LINUX_AT_RANDOM_LEN]; size_t execpath_len; struct proc *p; - int argc, envc; + int argc, envc, error; /* Calculate string base and vector table pointers. */ if (imgp->execpath != NULL && imgp->auxargs != NULL) @@ -237,7 +238,10 @@ if (execpath_len != 0) { imgp->execpathp = (uintptr_t)arginfo - execpath_len; - copyout(imgp->execpath, (void *)imgp->execpathp, execpath_len); + error = copyout(imgp->execpath, (void *)imgp->execpathp, + execpath_len); + if (error) + return (error); } /* Prepare the canary for SSP. */ @@ -245,11 +249,17 @@ imgp->canary = (uintptr_t)arginfo - roundup(execpath_len, sizeof(char *)) - roundup(sizeof(canary), sizeof(char *)); - copyout(canary, (void *)imgp->canary, sizeof(canary)); + error = copyout(canary, (void *)imgp->canary, sizeof(canary)); + if (error) + return (error); vectp = (char **)destp; - if (imgp->auxargs) - imgp->sysent->sv_copyout_auxargs(imgp, (u_long *)&vectp); + if (imgp->auxargs) { + error = imgp->sysent->sv_copyout_auxargs(imgp, + (u_long *)&vectp); + if (error) + return (error); + } /* * Allocate room for argc and the argv[] and env vectors including the @@ -259,45 +269,56 @@ vectp = (char **)STACKALIGN(vectp); /* vectp also becomes our initial stack base. */ - stack_base = (register_t *)vectp; + *stack_base = (register_t *)vectp; 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->args->stringspace); + error = copyout(stringp, destp, ARG_MAX - imgp->args->stringspace); + if (error) + return (error); /* Fill in "ps_strings" struct for ps, w, etc. */ - suword(&arginfo->ps_argvstr, (long)(intptr_t)vectp); - suword(&arginfo->ps_nargvstr, argc); + if (suword(&arginfo->ps_argvstr, (long)(intptr_t)vectp) != 0 || + suword(&arginfo->ps_nargvstr, argc) != 0) + return (EFAULT); + + if (suword(vectp++, argc) != 0) + return (EFAULT); - suword(vectp++, argc); /* Fill in argument portion of vector table. */ for (; argc > 0; --argc) { - suword(vectp++, (long)(intptr_t)destp); + if (suword(vectp++, (long)(intptr_t)destp) != 0) + return (EFAULT); while (*stringp++ != 0) destp++; destp++; } /* A null vector table pointer separates the argp's from the envp's. */ - suword(vectp++, 0); + if (suword(vectp++, 0) != 0) + return (EFAULT); - suword(&arginfo->ps_envstr, (long)(intptr_t)vectp); - suword(&arginfo->ps_nenvstr, envc); + if (suword(&arginfo->ps_envstr, (long)(intptr_t)vectp) != 0 || + suword(&arginfo->ps_nenvstr, envc) != 0) + return (EFAULT); /* Fill in environment portion of vector table. */ for (; envc > 0; --envc) { - suword(vectp++, (long)(intptr_t)destp); + if (suword(vectp++, (long)(intptr_t)destp) != 0) + return (EFAULT); while (*stringp++ != 0) destp++; destp++; } /* The end of the vector table is a null pointer. */ - suword(vectp, 0); - return (stack_base); + if (suword(vectp, 0) != 0) + return (EFAULT); + + return (0); } /* Index: sys/compat/cloudabi32/cloudabi32_module.c =================================================================== --- sys/compat/cloudabi32/cloudabi32_module.c +++ sys/compat/cloudabi32/cloudabi32_module.c @@ -45,8 +45,8 @@ extern char _binary_cloudabi32_vdso_o_start[]; extern char _binary_cloudabi32_vdso_o_end[]; -register_t * -cloudabi32_copyout_strings(struct image_params *imgp) +int +cloudabi32_copyout_strings(struct image_params *imgp, register_t **stack_base) { struct image_args *args; uintptr_t begin; @@ -56,8 +56,8 @@ args = imgp->args; len = exec_args_get_begin_envv(args) - args->begin_argv; begin = rounddown2(imgp->sysent->sv_usrstack - len, sizeof(register_t)); - copyout(args->begin_argv, (void *)begin, len); - return ((register_t *)begin); + *stack_base = (register_t *)begin; + return (copyout(args->begin_argv, (void *)begin, len)); } int Index: sys/compat/cloudabi32/cloudabi32_util.h =================================================================== --- sys/compat/cloudabi32/cloudabi32_util.h +++ sys/compat/cloudabi32/cloudabi32_util.h @@ -42,7 +42,7 @@ #define TO_PTR(x) ((void *)(uintptr_t)(x)) /* Stack initialization during process execution. */ -register_t *cloudabi32_copyout_strings(struct image_params *); +int cloudabi32_copyout_strings(struct image_params *, register_t **); int cloudabi32_fixup(register_t **, struct image_params *); int cloudabi32_thread_setregs(struct thread *, Index: sys/compat/cloudabi64/cloudabi64_module.c =================================================================== --- sys/compat/cloudabi64/cloudabi64_module.c +++ sys/compat/cloudabi64/cloudabi64_module.c @@ -45,8 +45,8 @@ extern char _binary_cloudabi64_vdso_o_start[]; extern char _binary_cloudabi64_vdso_o_end[]; -register_t * -cloudabi64_copyout_strings(struct image_params *imgp) +int +cloudabi64_copyout_strings(struct image_params *imgp, register_t **stack_base) { struct image_args *args; uintptr_t begin; @@ -56,8 +56,8 @@ args = imgp->args; len = exec_args_get_begin_envv(args) - args->begin_argv; begin = rounddown2(imgp->sysent->sv_usrstack - len, sizeof(register_t)); - copyout(args->begin_argv, (void *)begin, len); - return ((register_t *)begin); + *stack_base = (register_t *)begin; + return (copyout(args->begin_argv, (void *)begin, len)); } int Index: sys/compat/cloudabi64/cloudabi64_util.h =================================================================== --- sys/compat/cloudabi64/cloudabi64_util.h +++ sys/compat/cloudabi64/cloudabi64_util.h @@ -42,7 +42,7 @@ #define TO_PTR(x) ((void *)(uintptr_t)(x)) /* Stack initialization during process execution. */ -register_t *cloudabi64_copyout_strings(struct image_params *); +int cloudabi64_copyout_strings(struct image_params *, register_t **); int cloudabi64_fixup(register_t **, struct image_params *); int cloudabi64_thread_setregs(struct thread *, Index: sys/compat/freebsd32/freebsd32_misc.c =================================================================== --- sys/compat/freebsd32/freebsd32_misc.c +++ sys/compat/freebsd32/freebsd32_misc.c @@ -3119,19 +3119,18 @@ return (kern_syscall_helper_unregister(freebsd32_sysent, sd)); } -register_t * -freebsd32_copyout_strings(struct image_params *imgp) +int +freebsd32_copyout_strings(struct image_params *imgp, register_t **stack_base) { int argc, envc, i; u_int32_t *vectp; char *stringp; uintptr_t destp; - u_int32_t *stack_base; struct freebsd32_ps_strings *arginfo; char canary[sizeof(long) * 8]; int32_t pagesizes32[MAXPAGESIZES]; size_t execpath_len; - int szsigcode; + int error, szsigcode; /* * Calculate string base and vector table pointers. @@ -3155,8 +3154,10 @@ if (szsigcode != 0) { destp -= szsigcode; destp = rounddown2(destp, sizeof(uint32_t)); - copyout(imgp->proc->p_sysent->sv_sigcode, (void *)destp, + error = copyout(imgp->proc->p_sysent->sv_sigcode, (void *)destp, szsigcode); + if (error) + return (error); } /* @@ -3165,7 +3166,9 @@ if (execpath_len != 0) { destp -= execpath_len; imgp->execpathp = destp; - copyout(imgp->execpath, (void *)destp, execpath_len); + error = copyout(imgp->execpath, (void *)destp, execpath_len); + if (error) + return (error); } /* @@ -3174,7 +3177,9 @@ arc4rand(canary, sizeof(canary), 0); destp -= sizeof(canary); imgp->canary = destp; - copyout(canary, (void *)destp, sizeof(canary)); + error = copyout(canary, (void *)destp, sizeof(canary)); + if (error) + return (error); imgp->canarylen = sizeof(canary); /* @@ -3185,7 +3190,9 @@ destp -= sizeof(pagesizes32); destp = rounddown2(destp, sizeof(uint32_t)); imgp->pagesizes = destp; - copyout(pagesizes32, (void *)destp, sizeof(pagesizes32)); + error = copyout(pagesizes32, (void *)destp, sizeof(pagesizes32)); + if (error) + return (error); imgp->pagesizeslen = sizeof(pagesizes32); destp -= ARG_MAX - imgp->args->stringspace; @@ -3195,8 +3202,12 @@ if (imgp->sysent->sv_stackgap != NULL) imgp->sysent->sv_stackgap(imgp, (u_long *)&vectp); - if (imgp->auxargs) - imgp->sysent->sv_copyout_auxargs(imgp, (u_long *)&vectp); + if (imgp->auxargs) { + error = imgp->sysent->sv_copyout_auxargs(imgp, + (u_long *)&vectp); + if (error) + return (error); + } /* * Allocate room for the argv[] and env vectors including the @@ -3207,7 +3218,7 @@ /* * vectp also becomes our initial stack base */ - stack_base = vectp; + *stack_base = (register_t *)vectp; stringp = imgp->args->begin_argv; argc = imgp->args->argc; @@ -3215,44 +3226,53 @@ /* * Copy out strings - arguments and environment. */ - copyout(stringp, (void *)destp, ARG_MAX - imgp->args->stringspace); + error = copyout(stringp, (void *)destp, + ARG_MAX - imgp->args->stringspace); + if (error) + return (error); /* * Fill in "ps_strings" struct for ps, w, etc. */ - suword32(&arginfo->ps_argvstr, (u_int32_t)(intptr_t)vectp); - suword32(&arginfo->ps_nargvstr, argc); + if (suword32(&arginfo->ps_argvstr, (u_int32_t)(intptr_t)vectp) != 0 || + suword32(&arginfo->ps_nargvstr, argc) != 0) + return (EFAULT); /* * Fill in argument portion of vector table. */ for (; argc > 0; --argc) { - suword32(vectp++, (u_int32_t)(intptr_t)destp); + if (suword32(vectp++, (u_int32_t)(intptr_t)destp) != 0) + return (EFAULT); while (*stringp++ != 0) destp++; destp++; } /* a null vector table pointer separates the argp's from the envp's */ - suword32(vectp++, 0); + if (suword32(vectp++, 0) != 0) + return (EFAULT); - suword32(&arginfo->ps_envstr, (u_int32_t)(intptr_t)vectp); - suword32(&arginfo->ps_nenvstr, envc); + if (suword32(&arginfo->ps_envstr, (u_int32_t)(intptr_t)vectp) != 0 || + suword32(&arginfo->ps_nenvstr, envc) != 0) + return (EFAULT); /* * Fill in environment portion of vector table. */ for (; envc > 0; --envc) { - suword32(vectp++, (u_int32_t)(intptr_t)destp); + if (suword32(vectp++, (u_int32_t)(intptr_t)destp) != 0) + return (EFAULT); while (*stringp++ != 0) destp++; destp++; } /* end of vector table is a null pointer */ - suword32(vectp, 0); + if (suword32(vectp, 0) != 0) + return (EFAULT); - return ((register_t *)stack_base); + return (0); } int Index: sys/compat/freebsd32/freebsd32_util.h =================================================================== --- sys/compat/freebsd32/freebsd32_util.h +++ sys/compat/freebsd32/freebsd32_util.h @@ -112,7 +112,8 @@ struct iovec32; struct rusage32; -register_t *freebsd32_copyout_strings(struct image_params *imgp); +int freebsd32_copyout_strings(struct image_params *imgp, + register_t **stack_base); int freebsd32_copyiniov(struct iovec32 *iovp, u_int iovcnt, struct iovec **iov, int error); void freebsd32_rusage_out(const struct rusage *s, struct rusage32 *s32); Index: sys/i386/linux/linux_sysvec.c =================================================================== --- sys/i386/linux/linux_sysvec.c +++ sys/i386/linux/linux_sysvec.c @@ -95,7 +95,8 @@ static void linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask); static void linux_exec_setregs(struct thread *td, struct image_params *imgp, u_long stack); -static register_t *linux_copyout_strings(struct image_params *imgp); +static int linux_copyout_strings(struct image_params *imgp, + register_t **stack_base); static bool linux_trans_osrel(const Elf_Note *note, int32_t *osrel); static void linux_vdso_install(void *param); static void linux_vdso_deinstall(void *param); @@ -188,7 +189,7 @@ return (0); } -static void +static int linux_copyout_auxargs(struct image_params *imgp, u_long *base) { struct proc *p; @@ -197,7 +198,7 @@ Elf32_Addr *uplatform; struct ps_strings *arginfo; u_long auxlen; - int issetugid; + int error, issetugid; p = imgp->proc; issetugid = imgp->proc->p_flag & P_SUGID ? 1 : 0; @@ -248,8 +249,9 @@ auxlen = sizeof(*argarray) * (pos - argarray); *base -= auxlen; - copyout(argarray, (void *)*base, auxlen); + error = copyout(argarray, (void *)*base, auxlen); free(argarray, M_TEMP); + return (error); } static int @@ -265,13 +267,12 @@ /* * Copied from kern/kern_exec.c */ -static register_t * -linux_copyout_strings(struct image_params *imgp) +static int +linux_copyout_strings(struct image_params *imgp, register_t **stack_base) { - int argc, envc; + int argc, envc, error; char **vectp; char *stringp, *destp; - register_t *stack_base; struct ps_strings *arginfo; char canary[LINUX_AT_RANDOM_LEN]; size_t execpath_len; @@ -290,13 +291,18 @@ roundup(ARG_MAX - imgp->args->stringspace, sizeof(char *)); /* Install LINUX_PLATFORM. */ - copyout(linux_kplatform, ((caddr_t)arginfo - linux_szplatform), + error = copyout(linux_kplatform, ((caddr_t)arginfo - linux_szplatform), linux_szplatform); + if (error) + return (error); if (execpath_len != 0) { imgp->execpathp = (uintptr_t)arginfo - linux_szplatform - execpath_len; - copyout(imgp->execpath, (void *)imgp->execpathp, execpath_len); + error = copyout(imgp->execpath, (void *)imgp->execpathp, + execpath_len); + if (error) + return (error); } /* Prepare the canary for SSP. */ @@ -304,11 +310,17 @@ imgp->canary = (uintptr_t)arginfo - linux_szplatform - roundup(execpath_len, sizeof(char *)) - roundup(sizeof(canary), sizeof(char *)); - copyout(canary, (void *)imgp->canary, sizeof(canary)); + error = copyout(canary, (void *)imgp->canary, sizeof(canary)); + if (error) + return (error); vectp = (char **)destp; - if (imgp->auxargs) - imgp->sysent->sv_copyout_auxargs(imgp, (u_long *)&vectp); + if (imgp->auxargs) { + error = imgp->sysent->sv_copyout_auxargs(imgp, + (u_long *)&vectp); + if (error) + return (error); + } /* * Allocate room for the argv[] and env vectors including the @@ -317,45 +329,53 @@ vectp -= imgp->args->argc + 1 + imgp->args->envc + 1; /* vectp also becomes our initial stack base. */ - stack_base = (register_t *)vectp; + *stack_base = (register_t *)vectp; 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->args->stringspace); + error = copyout(stringp, destp, ARG_MAX - imgp->args->stringspace); + if (error) + return (error); /* Fill in "ps_strings" struct for ps, w, etc. */ - suword(&arginfo->ps_argvstr, (long)(intptr_t)vectp); - suword(&arginfo->ps_nargvstr, argc); + if (suword(&arginfo->ps_argvstr, (long)(intptr_t)vectp) != 0 || + suword(&arginfo->ps_nargvstr, argc) != 0) + return (EFAULT); /* Fill in argument portion of vector table. */ for (; argc > 0; --argc) { - suword(vectp++, (long)(intptr_t)destp); + if (suword(vectp++, (long)(intptr_t)destp) != 0) + return (EFAULT); while (*stringp++ != 0) destp++; destp++; } /* A null vector table pointer separates the argp's from the envp's. */ - suword(vectp++, 0); + if (suword(vectp++, 0) != 0) + return (EFAULT); - suword(&arginfo->ps_envstr, (long)(intptr_t)vectp); - suword(&arginfo->ps_nenvstr, envc); + if (suword(&arginfo->ps_envstr, (long)(intptr_t)vectp) != 0 || + suword(&arginfo->ps_nenvstr, envc) != 0) + return (EFAULT); /* Fill in environment portion of vector table. */ for (; envc > 0; --envc) { - suword(vectp++, (long)(intptr_t)destp); + if (suword(vectp++, (long)(intptr_t)destp) != 0) + return (EFAULT); while (*stringp++ != 0) destp++; destp++; } /* The end of the vector table is a null pointer. */ - suword(vectp, 0); + if (suword(vectp, 0) != 0) + return (EFAULT); - return (stack_base); + return (0); } static void Index: sys/kern/imgact_elf.c =================================================================== --- sys/kern/imgact_elf.c +++ sys/kern/imgact_elf.c @@ -1323,12 +1323,13 @@ #define suword __CONCAT(suword, __ELF_WORD_SIZE) -void +int __elfN(freebsd_copyout_auxargs)(struct image_params *imgp, u_long *base) { Elf_Auxargs *args = (Elf_Auxargs *)imgp->auxargs; Elf_Auxinfo *argarray, *pos; u_long auxlen; + int error; argarray = pos = malloc(AT_COUNT * sizeof(*pos), M_TEMP, M_WAITOK | M_ZERO); @@ -1375,8 +1376,9 @@ auxlen = sizeof(*argarray) * (pos - argarray); *base -= auxlen; - copyout(argarray, (void *)*base, auxlen); + error = copyout(argarray, (void *)*base, auxlen); free(argarray, M_TEMP); + return (error); } int Index: sys/kern/kern_exec.c =================================================================== --- sys/kern/kern_exec.c +++ sys/kern/kern_exec.c @@ -669,7 +669,11 @@ /* * Copy out strings (args and env) and initialize stack base. */ - stack_base = (*p->p_sysent->sv_copyout_strings)(imgp); + error = (*p->p_sysent->sv_copyout_strings)(imgp, &stack_base); + if (error != 0) { + vn_lock(imgp->vp, LK_SHARED | LK_RETRY); + goto exec_fail_dealloc; + } /* * Stack setup. @@ -1561,18 +1565,17 @@ * and env vector tables. Return a pointer to the base so that it can be used * as the initial stack pointer. */ -register_t * -exec_copyout_strings(struct image_params *imgp) +int +exec_copyout_strings(struct image_params *imgp, register_t **stack_base) { int argc, envc; char **vectp; char *stringp; uintptr_t destp; - register_t *stack_base; struct ps_strings *arginfo; struct proc *p; size_t execpath_len; - int szsigcode, szps; + int error, szsigcode, szps; char canary[sizeof(long) * 8]; szps = sizeof(pagesizes[0]) * MAXPAGESIZES; @@ -1599,7 +1602,10 @@ if (szsigcode != 0) { destp -= szsigcode; destp = rounddown2(destp, sizeof(void *)); - copyout(p->p_sysent->sv_sigcode, (void *)destp, szsigcode); + error = copyout(p->p_sysent->sv_sigcode, (void *)destp, + szsigcode); + if (error) + return (error); } /* @@ -1609,7 +1615,9 @@ destp -= execpath_len; destp = rounddown2(destp, sizeof(void *)); imgp->execpathp = destp; - copyout(imgp->execpath, (void *)destp, execpath_len); + error = copyout(imgp->execpath, (void *)destp, execpath_len); + if (error) + return (error); } /* @@ -1618,7 +1626,9 @@ arc4rand(canary, sizeof(canary), 0); destp -= sizeof(canary); imgp->canary = destp; - copyout(canary, (void *)destp, sizeof(canary)); + error = copyout(canary, (void *)destp, sizeof(canary)); + if (error) + return (error); imgp->canarylen = sizeof(canary); /* @@ -1627,7 +1637,9 @@ destp -= szps; destp = rounddown2(destp, sizeof(void *)); imgp->pagesizes = destp; - copyout(pagesizes, (void *)destp, szps); + error = copyout(pagesizes, (void *)destp, szps); + if (error) + return (error); imgp->pagesizeslen = szps; destp -= ARG_MAX - imgp->args->stringspace; @@ -1637,8 +1649,12 @@ if (imgp->sysent->sv_stackgap != NULL) imgp->sysent->sv_stackgap(imgp, (u_long *)&vectp); - if (imgp->auxargs) - imgp->sysent->sv_copyout_auxargs(imgp, (u_long *)&vectp); + if (imgp->auxargs) { + error = imgp->sysent->sv_copyout_auxargs(imgp, + (u_long *)&vectp); + if (error) + return (error); + } /* * Allocate room for the argv[] and env vectors including the @@ -1649,7 +1665,7 @@ /* * vectp also becomes our initial stack base */ - stack_base = (register_t *)vectp; + *stack_base = (register_t *)vectp; stringp = imgp->args->begin_argv; argc = imgp->args->argc; @@ -1658,44 +1674,53 @@ /* * Copy out strings - arguments and environment. */ - copyout(stringp, (void *)destp, ARG_MAX - imgp->args->stringspace); + error = copyout(stringp, (void *)destp, + ARG_MAX - imgp->args->stringspace); + if (error) + return (error); /* * Fill in "ps_strings" struct for ps, w, etc. */ - suword(&arginfo->ps_argvstr, (long)(intptr_t)vectp); - suword32(&arginfo->ps_nargvstr, argc); + if (suword(&arginfo->ps_argvstr, (long)(intptr_t)vectp) != 0 || + suword32(&arginfo->ps_nargvstr, argc) != 0) + return (EFAULT); /* * Fill in argument portion of vector table. */ for (; argc > 0; --argc) { - suword(vectp++, (long)(intptr_t)destp); + if (suword(vectp++, (long)(intptr_t)destp) != 0) + return (EFAULT); while (*stringp++ != 0) destp++; destp++; } /* a null vector table pointer separates the argp's from the envp's */ - suword(vectp++, 0); + if (suword(vectp++, 0) != 0) + return (EFAULT); - suword(&arginfo->ps_envstr, (long)(intptr_t)vectp); - suword32(&arginfo->ps_nenvstr, envc); + if (suword(&arginfo->ps_envstr, (long)(intptr_t)vectp) != 0 || + suword32(&arginfo->ps_nenvstr, envc) != 0) + return (EFAULT); /* * Fill in environment portion of vector table. */ for (; envc > 0; --envc) { - suword(vectp++, (long)(intptr_t)destp); + if (suword(vectp++, (long)(intptr_t)destp) != 0) + return (EFAULT); while (*stringp++ != 0) destp++; destp++; } /* end of vector table is a null pointer */ - suword(vectp, 0); + if (suword(vectp, 0) != 0) + return (EFAULT); - return (stack_base); + return (0); } /* Index: sys/sys/imgact.h =================================================================== --- sys/sys/imgact.h +++ sys/sys/imgact.h @@ -110,7 +110,7 @@ ssize_t extend); char *exec_args_get_begin_envv(struct image_args *args); int exec_check_permissions(struct image_params *); -register_t *exec_copyout_strings(struct image_params *); +int exec_copyout_strings(struct image_params *, register_t **); void exec_free_args(struct image_args *); int exec_new_vmspace(struct image_params *, struct sysentvec *); void exec_setregs(struct thread *, struct image_params *, u_long); Index: sys/sys/imgact_elf.h =================================================================== --- sys/sys/imgact_elf.h +++ sys/sys/imgact_elf.h @@ -99,7 +99,7 @@ int __elfN(coredump)(struct thread *, struct vnode *, off_t, int); size_t __elfN(populate_note)(int, void *, void *, size_t, void **); void __elfN(stackgap)(struct image_params *, u_long *); -void __elfN(freebsd_copyout_auxargs)(struct image_params *, u_long *); +int __elfN(freebsd_copyout_auxargs)(struct image_params *, u_long *); /* Machine specific function to dump per-thread information. */ void __elfN(dump_thread)(struct thread *, void *, size_t *); Index: sys/sys/sysent.h =================================================================== --- sys/sys/sysent.h +++ sys/sys/sysent.h @@ -110,14 +110,14 @@ /* function to dump core, or NULL */ int (*sv_imgact_try)(struct image_params *); void (*sv_stackgap)(struct image_params *, u_long *); - void (*sv_copyout_auxargs)(struct image_params *, u_long *); + int (*sv_copyout_auxargs)(struct image_params *, u_long *); int sv_minsigstksz; /* minimum signal stack size */ vm_offset_t sv_minuser; /* VM_MIN_ADDRESS */ vm_offset_t sv_maxuser; /* VM_MAXUSER_ADDRESS */ vm_offset_t sv_usrstack; /* USRSTACK */ vm_offset_t sv_psstrings; /* PS_STRINGS */ int sv_stackprot; /* vm protection for stack */ - register_t *(*sv_copyout_strings)(struct image_params *); + int (*sv_copyout_strings)(struct image_params *, register_t **); void (*sv_setregs)(struct thread *, struct image_params *, u_long); void (*sv_fixlimit)(struct rlimit *, int);