Index: head/sys/amd64/linux/linux_sysvec.c =================================================================== --- head/sys/amd64/linux/linux_sysvec.c +++ head/sys/amd64/linux/linux_sysvec.c @@ -240,11 +240,11 @@ linux_fixup_elf(register_t **stack_base, struct image_params *imgp) { Elf_Auxargs *args; - Elf_Addr *base; - Elf_Addr *pos; + Elf_Auxinfo *argarray, *pos; + Elf_Addr *auxbase, *base; struct ps_strings *arginfo; struct proc *p; - int issetugid; + int error, issetugid; p = imgp->proc; arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings; @@ -253,7 +253,9 @@ ("unsafe linux_fixup_elf(), should be curproc")); base = (Elf64_Addr *)*stack_base; args = (Elf64_Auxargs *)imgp->auxargs; - pos = base + (imgp->args->argc + imgp->args->envc + 2); + auxbase = base + imgp->args->argc + 1 + imgp->args->envc + 1; + argarray = pos = malloc(LINUX_AT_COUNT * sizeof(*pos), M_TEMP, + M_WAITOK | M_ZERO); issetugid = p->p_flag & P_SUGID ? 1 : 0; AUXARGS_ENTRY(pos, LINUX_AT_SYSINFO_EHDR, @@ -281,9 +283,17 @@ AUXARGS_ENTRY(pos, AT_NULL, 0); free(imgp->auxargs, M_TEMP); imgp->auxargs = NULL; + KASSERT((pos - argarray) / sizeof(*pos) <= LINUX_AT_COUNT, + ("Too many auxargs")); + error = copyout(argarray, auxbase, sizeof(*argarray) * LINUX_AT_COUNT); + free(argarray, M_TEMP); + if (error != 0) + return (error); + base--; - suword(base, (uint64_t)imgp->args->argc); + if (suword(base, (uint64_t)imgp->args->argc) == -1) + return (EFAULT); *stack_base = (register_t *)base; return (0); Index: head/sys/amd64/linux32/linux32_sysvec.c =================================================================== --- head/sys/amd64/linux32/linux32_sysvec.c +++ head/sys/amd64/linux32/linux32_sysvec.c @@ -89,12 +89,6 @@ MODULE_VERSION(linux, 1); -#define AUXARGS_ENTRY_32(pos, id, val) \ - do { \ - suword32(pos++, id); \ - suword32(pos++, val); \ - } while (0) - /* * Allow the sendsig functions to use the ldebug() facility even though they * are not syscalls themselves. Map them to syscall 0. This is slightly less @@ -202,10 +196,10 @@ linux_fixup_elf(register_t **stack_base, struct image_params *imgp) { Elf32_Auxargs *args; - Elf32_Addr *base; - Elf32_Addr *pos; + Elf32_Auxinfo *argarray, *pos; + Elf32_Addr *auxbase, *base; struct linux32_ps_strings *arginfo; - int issetugid; + int error, issetugid; arginfo = (struct linux32_ps_strings *)LINUX32_PS_STRINGS; @@ -213,13 +207,15 @@ ("unsafe linux_fixup_elf(), should be curproc")); base = (Elf32_Addr *)*stack_base; args = (Elf32_Auxargs *)imgp->auxargs; - pos = base + (imgp->args->argc + imgp->args->envc + 2); + auxbase = base + (imgp->args->argc + 1 + imgp->args->envc + 1); + argarray = pos = malloc(LINUX_AT_COUNT * sizeof(*pos), M_TEMP, + M_WAITOK | M_ZERO); issetugid = imgp->proc->p_flag & P_SUGID ? 1 : 0; - AUXARGS_ENTRY_32(pos, LINUX_AT_SYSINFO_EHDR, + AUXARGS_ENTRY(pos, LINUX_AT_SYSINFO_EHDR, imgp->proc->p_sysent->sv_shared_page_base); - AUXARGS_ENTRY_32(pos, LINUX_AT_SYSINFO, linux32_vsyscall); - AUXARGS_ENTRY_32(pos, LINUX_AT_HWCAP, cpu_feature); + AUXARGS_ENTRY(pos, LINUX_AT_SYSINFO, linux32_vsyscall); + AUXARGS_ENTRY(pos, LINUX_AT_HWCAP, cpu_feature); /* * Do not export AT_CLKTCK when emulating Linux kernel prior to 2.4.0, @@ -230,32 +226,40 @@ * Also see linux_times() implementation. */ if (linux_kernver(curthread) >= LINUX_KERNVER_2004000) - AUXARGS_ENTRY_32(pos, LINUX_AT_CLKTCK, stclohz); - AUXARGS_ENTRY_32(pos, AT_PHDR, args->phdr); - AUXARGS_ENTRY_32(pos, AT_PHENT, args->phent); - AUXARGS_ENTRY_32(pos, AT_PHNUM, args->phnum); - AUXARGS_ENTRY_32(pos, AT_PAGESZ, args->pagesz); - AUXARGS_ENTRY_32(pos, AT_FLAGS, args->flags); - AUXARGS_ENTRY_32(pos, AT_ENTRY, args->entry); - AUXARGS_ENTRY_32(pos, AT_BASE, args->base); - AUXARGS_ENTRY_32(pos, LINUX_AT_SECURE, issetugid); - AUXARGS_ENTRY_32(pos, AT_UID, imgp->proc->p_ucred->cr_ruid); - AUXARGS_ENTRY_32(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid); - AUXARGS_ENTRY_32(pos, AT_GID, imgp->proc->p_ucred->cr_rgid); - AUXARGS_ENTRY_32(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid); - AUXARGS_ENTRY_32(pos, LINUX_AT_PLATFORM, PTROUT(linux_platform)); + AUXARGS_ENTRY(pos, LINUX_AT_CLKTCK, stclohz); + AUXARGS_ENTRY(pos, AT_PHDR, args->phdr); + AUXARGS_ENTRY(pos, AT_PHENT, args->phent); + AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum); + AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz); + AUXARGS_ENTRY(pos, AT_FLAGS, args->flags); + AUXARGS_ENTRY(pos, AT_ENTRY, args->entry); + AUXARGS_ENTRY(pos, AT_BASE, args->base); + AUXARGS_ENTRY(pos, LINUX_AT_SECURE, issetugid); + AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_ucred->cr_ruid); + AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid); + AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_ucred->cr_rgid); + AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid); + AUXARGS_ENTRY(pos, LINUX_AT_PLATFORM, PTROUT(linux_platform)); AUXARGS_ENTRY(pos, LINUX_AT_RANDOM, PTROUT(imgp->canary)); if (imgp->execpathp != 0) AUXARGS_ENTRY(pos, LINUX_AT_EXECFN, PTROUT(imgp->execpathp)); if (args->execfd != -1) - AUXARGS_ENTRY_32(pos, AT_EXECFD, args->execfd); - AUXARGS_ENTRY_32(pos, AT_NULL, 0); + AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); + AUXARGS_ENTRY(pos, AT_NULL, 0); free(imgp->auxargs, M_TEMP); imgp->auxargs = NULL; + KASSERT((pos - argarray) / sizeof(*pos) <= AT_COUNT, + ("Too many auxargs")); + error = copyout(&argarray[0], auxbase, sizeof(*argarray) * AT_COUNT); + free(argarray, M_TEMP); + if (error != 0) + return (error); + base--; - suword32(base, (uint32_t)imgp->args->argc); + if (suword32(base, (uint32_t)imgp->args->argc) == -1) + return (EFAULT); *stack_base = (register_t *)base; return (0); } Index: head/sys/i386/linux/linux_sysvec.c =================================================================== --- head/sys/i386/linux/linux_sysvec.c +++ head/sys/i386/linux/linux_sysvec.c @@ -207,10 +207,10 @@ { struct proc *p; Elf32_Auxargs *args; - Elf32_Addr *uplatform; + Elf32_Auxinfo *argarray, *pos; + Elf32_Addr *auxbase, *uplatform; struct ps_strings *arginfo; - register_t *pos; - int issetugid; + int error, issetugid; KASSERT(curthread->td_proc == imgp->proc, ("unsafe linux_fixup_elf(), should be curproc")); @@ -220,7 +220,9 @@ arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings; uplatform = (Elf32_Addr *)((caddr_t)arginfo - linux_szplatform); args = (Elf32_Auxargs *)imgp->auxargs; - pos = *stack_base + (imgp->args->argc + imgp->args->envc + 2); + auxbase = *stack_base + imgp->args->argc + 1 + imgp->args->envc + 1; + argarray = pos = malloc(LINUX_AT_COUNT * sizeof(*pos), M_TEMP, + M_WAITOK | M_ZERO); AUXARGS_ENTRY(pos, LINUX_AT_SYSINFO_EHDR, imgp->proc->p_sysent->sv_shared_page_base); @@ -259,9 +261,17 @@ free(imgp->auxargs, M_TEMP); imgp->auxargs = NULL; + KASSERT((pos - argarray) / sizeof(*pos) <= LINUX_AT_COUNT, + ("Too many auxargs")); + error = copyout(argarray, auxbase, sizeof(*argarray) * LINUX_AT_COUNT); + free(argarray, M_TEMP); + if (error != 0) + return (error); + (*stack_base)--; - suword(*stack_base, (register_t)imgp->args->argc); + if (suword(*stack_base, (register_t)imgp->args->argc) == -1) + return (EFAULT); return (0); } Index: head/sys/kern/imgact_elf.c =================================================================== --- head/sys/kern/imgact_elf.c +++ head/sys/kern/imgact_elf.c @@ -1098,11 +1098,14 @@ __elfN(freebsd_fixup)(register_t **stack_base, struct image_params *imgp) { Elf_Auxargs *args = (Elf_Auxargs *)imgp->auxargs; - Elf_Addr *base; - Elf_Addr *pos; + Elf_Auxinfo *argarray, *pos; + Elf_Addr *base, *auxbase; + int error; base = (Elf_Addr *)*stack_base; - pos = base + (imgp->args->argc + imgp->args->envc + 2); + auxbase = base + imgp->args->argc + 1 + imgp->args->envc + 1; + argarray = pos = malloc(AT_COUNT * sizeof(*pos), M_TEMP, + M_WAITOK | M_ZERO); if (args->execfd != -1) AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); @@ -1142,9 +1145,17 @@ free(imgp->auxargs, M_TEMP); imgp->auxargs = NULL; + KASSERT((pos - argarray) / sizeof(*pos) <= AT_COUNT, + ("Too many auxargs")); + error = copyout(argarray, auxbase, sizeof(*argarray) * AT_COUNT); + free(argarray, M_TEMP); + if (error != 0) + return (error); + base--; - suword(base, (long)imgp->args->argc); + if (suword(base, imgp->args->argc) == -1) + return (EFAULT); *stack_base = (register_t *)base; return (0); } Index: head/sys/kern/kern_exec.c =================================================================== --- head/sys/kern/kern_exec.c +++ head/sys/kern/kern_exec.c @@ -691,9 +691,12 @@ * Else stuff argument count as first item on stack */ if (p->p_sysent->sv_fixup != NULL) - (*p->p_sysent->sv_fixup)(&stack_base, imgp); + error = (*p->p_sysent->sv_fixup)(&stack_base, imgp); else - suword(--stack_base, imgp->args->argc); + error = suword(--stack_base, imgp->args->argc) == 0 ? + 0 : EFAULT; + if (error != 0) + goto exec_fail_dealloc; if (args->fdp != NULL) { /* Install a brand new file descriptor table. */ Index: head/sys/sys/imgact_elf.h =================================================================== --- head/sys/sys/imgact_elf.h +++ head/sys/sys/imgact_elf.h @@ -37,7 +37,8 @@ #ifdef _KERNEL -#define AUXARGS_ENTRY(pos, id, val) {suword(pos++, id); suword(pos++, val);} +#define AUXARGS_ENTRY(pos, id, val) \ + {(pos)->a_type = (id); (pos)->a_un.a_val = (val); (pos)++;} struct image_params; struct thread;