Check for errors from copyout() and suword*() in sv_copyout_args/strings.

Reviewed by:	brooks, kib
Tested on:	amd64 (amd64, i386, linux64), i386 (i386, linux)
Sponsored by:	DARPA
Differential Revision:	https://reviews.freebsd.org/D22401
This commit is contained in:
jhb 2019-11-18 20:07:43 +00:00
parent 8d166fea2a
commit 81f62ee15e
15 changed files with 280 additions and 154 deletions

View File

@ -96,7 +96,8 @@ extern struct sysent linux_sysent[LINUX_SYS_MAXSYSCALL];
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 @@ linux_set_syscall_retval(struct thread *td, int error)
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 @@ linux_copyout_auxargs(struct image_params *imgp, u_long *base)
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 @@ linux_fixup_elf(register_t **stack_base, struct image_params *imgp)
* 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 @@ linux_copyout_strings(struct image_params *imgp)
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 != 0)
return (error);
}
/* Prepare the canary for SSP. */
@ -325,7 +329,9 @@ linux_copyout_strings(struct image_params *imgp)
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 != 0)
return (error);
vectp = (char **)destp;
@ -335,8 +341,12 @@ linux_copyout_strings(struct image_params *imgp)
*/
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 != 0)
return (error);
}
/*
* Allocate room for the argv[] and env vectors including the
@ -345,44 +355,53 @@ linux_copyout_strings(struct image_params *imgp)
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 != 0)
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);
}
/*

View File

@ -103,7 +103,8 @@ SET_DECLARE(linux_ioctl_handler_set, struct linux_ioctl_handler);
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 @@ linux_translate_traps(int signal, int trap_code)
}
}
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 @@ linux_copyout_auxargs(struct image_params *imgp, u_long *base)
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 @@ linux_exec_setregs(struct thread *td, struct image_params *imgp, u_long stack)
/*
* 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 @@ linux_copyout_strings(struct image_params *imgp)
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 != 0)
return (error);
}
/* Prepare the canary for SSP. */
@ -751,11 +755,17 @@ linux_copyout_strings(struct image_params *imgp)
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 != 0)
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 != 0)
return (error);
}
/*
* Allocate room for the argv[] and env vectors including the
@ -764,44 +774,52 @@ linux_copyout_strings(struct image_params *imgp)
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 != 0)
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,

View File

@ -69,7 +69,8 @@ extern struct sysent linux_sysent[LINUX_SYS_MAXSYSCALL];
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 @@ linux_set_syscall_retval(struct thread *td, int error)
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 @@ linux_copyout_auxargs(struct image_params *imgp, u_long *base)
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 @@ linux_elf_fixup(register_t **stack_base, struct image_params *imgp)
* 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 @@ linux_copyout_strings(struct image_params *imgp)
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 != 0)
return (error);
}
/* Prepare the canary for SSP. */
@ -245,11 +249,17 @@ linux_copyout_strings(struct image_params *imgp)
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 != 0)
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 != 0)
return (error);
}
/*
* Allocate room for argc and the argv[] and env vectors including the
@ -259,45 +269,56 @@ linux_copyout_strings(struct image_params *imgp)
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 != 0)
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);
}
/*

View File

@ -45,8 +45,8 @@ __FBSDID("$FreeBSD$");
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 @@ cloudabi32_copyout_strings(struct image_params *imgp)
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

View File

@ -42,7 +42,7 @@ extern Elf32_Brandinfo cloudabi32_brand;
#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 *,

View File

@ -45,8 +45,8 @@ __FBSDID("$FreeBSD$");
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 @@ cloudabi64_copyout_strings(struct image_params *imgp)
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

View File

@ -42,7 +42,7 @@ extern Elf64_Brandinfo cloudabi64_brand;
#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 *,

View File

@ -3119,19 +3119,18 @@ syscall32_helper_unregister(struct syscall_helper_data *sd)
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 @@ freebsd32_copyout_strings(struct image_params *imgp)
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 != 0)
return (error);
}
/*
@ -3165,7 +3166,9 @@ freebsd32_copyout_strings(struct image_params *imgp)
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 != 0)
return (error);
}
/*
@ -3174,7 +3177,9 @@ freebsd32_copyout_strings(struct image_params *imgp)
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 != 0)
return (error);
imgp->canarylen = sizeof(canary);
/*
@ -3185,7 +3190,9 @@ freebsd32_copyout_strings(struct image_params *imgp)
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 != 0)
return (error);
imgp->pagesizeslen = sizeof(pagesizes32);
destp -= ARG_MAX - imgp->args->stringspace;
@ -3195,8 +3202,12 @@ freebsd32_copyout_strings(struct image_params *imgp)
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 != 0)
return (error);
}
/*
* Allocate room for the argv[] and env vectors including the
@ -3207,7 +3218,7 @@ freebsd32_copyout_strings(struct image_params *imgp)
/*
* 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 @@ freebsd32_copyout_strings(struct image_params *imgp)
/*
* 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 != 0)
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

View File

@ -112,7 +112,8 @@ int syscall32_helper_unregister(struct syscall_helper_data *sd);
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);

View File

@ -95,7 +95,8 @@ static int linux_fixup_elf(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);
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 @@ linux_fixup(register_t **stack_base, struct image_params *imgp)
return (0);
}
static void
static int
linux_copyout_auxargs(struct image_params *imgp, u_long *base)
{
struct proc *p;
@ -197,7 +198,7 @@ linux_copyout_auxargs(struct image_params *imgp, u_long *base)
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 @@ linux_copyout_auxargs(struct image_params *imgp, u_long *base)
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 @@ linux_fixup_elf(register_t **stack_base, struct image_params *imgp)
/*
* 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 @@ linux_copyout_strings(struct image_params *imgp)
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 != 0)
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 != 0)
return (error);
}
/* Prepare the canary for SSP. */
@ -304,11 +310,17 @@ linux_copyout_strings(struct image_params *imgp)
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 != 0)
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 != 0)
return (error);
}
/*
* Allocate room for the argv[] and env vectors including the
@ -317,45 +329,53 @@ linux_copyout_strings(struct image_params *imgp)
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 != 0)
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

View File

@ -1323,12 +1323,13 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
#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 @@ __elfN(freebsd_copyout_auxargs)(struct image_params *imgp, u_long *base)
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

View File

@ -672,7 +672,11 @@ do_execve(struct thread *td, struct image_args *args, struct mac *mac_p)
/*
* 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.
@ -1569,18 +1573,17 @@ exec_args_get_begin_envv(struct image_args *args)
* 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;
@ -1607,7 +1610,10 @@ exec_copyout_strings(struct image_params *imgp)
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 != 0)
return (error);
}
/*
@ -1617,7 +1623,9 @@ exec_copyout_strings(struct image_params *imgp)
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 != 0)
return (error);
}
/*
@ -1626,7 +1634,9 @@ exec_copyout_strings(struct image_params *imgp)
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 != 0)
return (error);
imgp->canarylen = sizeof(canary);
/*
@ -1635,7 +1645,9 @@ exec_copyout_strings(struct image_params *imgp)
destp -= szps;
destp = rounddown2(destp, sizeof(void *));
imgp->pagesizes = destp;
copyout(pagesizes, (void *)destp, szps);
error = copyout(pagesizes, (void *)destp, szps);
if (error != 0)
return (error);
imgp->pagesizeslen = szps;
destp -= ARG_MAX - imgp->args->stringspace;
@ -1645,8 +1657,12 @@ exec_copyout_strings(struct image_params *imgp)
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 != 0)
return (error);
}
/*
* Allocate room for the argv[] and env vectors including the
@ -1657,7 +1673,7 @@ exec_copyout_strings(struct image_params *imgp)
/*
* 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;
@ -1666,44 +1682,53 @@ exec_copyout_strings(struct image_params *imgp)
/*
* 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 != 0)
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);
}
/*

View File

@ -110,7 +110,7 @@ int exec_args_adjust_args(struct image_args *args, size_t consume,
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);

View File

@ -99,7 +99,7 @@ int __elfN(freebsd_fixup)(register_t **, struct image_params *);
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 *);

View File

@ -110,14 +110,14 @@ struct sysentvec {
/* 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);