aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2019-11-18 20:07:43 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2019-11-18 20:07:43 +0000
commit03b0d68c7237a1610185bf8adbcdcc51cc1c3823 (patch)
tree2fcea92c35e69703d2128f14eb0513c93916f66d
parent85e06c728c68131e155a5e7138bec7f300d82433 (diff)
downloadsrc-03b0d68c7237a1610185bf8adbcdcc51cc1c3823.tar.gz
src-03b0d68c7237a1610185bf8adbcdcc51cc1c3823.zip
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
Notes
Notes: svn path=/head/; revision=354827
-rw-r--r--sys/amd64/linux/linux_sysvec.c65
-rw-r--r--sys/amd64/linux32/linux32_sysvec.c64
-rw-r--r--sys/arm64/linux/linux_sysvec.c69
-rw-r--r--sys/compat/cloudabi32/cloudabi32_module.c8
-rw-r--r--sys/compat/cloudabi32/cloudabi32_util.h2
-rw-r--r--sys/compat/cloudabi64/cloudabi64_module.c8
-rw-r--r--sys/compat/cloudabi64/cloudabi64_util.h2
-rw-r--r--sys/compat/freebsd32/freebsd32_misc.c62
-rw-r--r--sys/compat/freebsd32/freebsd32_util.h3
-rw-r--r--sys/i386/linux/linux_sysvec.c68
-rw-r--r--sys/kern/imgact_elf.c6
-rw-r--r--sys/kern/kern_exec.c69
-rw-r--r--sys/sys/imgact.h2
-rw-r--r--sys/sys/imgact_elf.h2
-rw-r--r--sys/sys/sysent.h4
15 files changed, 280 insertions, 154 deletions
diff --git a/sys/amd64/linux/linux_sysvec.c b/sys/amd64/linux/linux_sysvec.c
index eb7daa63d8e7..303203226136 100644
--- a/sys/amd64/linux/linux_sysvec.c
+++ b/sys/amd64/linux/linux_sysvec.c
@@ -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);
}
/*
diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c
index 675834daeeab..ba87152d7a9a 100644
--- a/sys/amd64/linux32/linux32_sysvec.c
+++ b/sys/amd64/linux32/linux32_sysvec.c
@@ -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,
diff --git a/sys/arm64/linux/linux_sysvec.c b/sys/arm64/linux/linux_sysvec.c
index b36b8cbdc64c..43d7a9bb0b41 100644
--- a/sys/arm64/linux/linux_sysvec.c
+++ b/sys/arm64/linux/linux_sysvec.c
@@ -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);
}
/*
diff --git a/sys/compat/cloudabi32/cloudabi32_module.c b/sys/compat/cloudabi32/cloudabi32_module.c
index 51beae7519ac..9170e49eda30 100644
--- a/sys/compat/cloudabi32/cloudabi32_module.c
+++ b/sys/compat/cloudabi32/cloudabi32_module.c
@@ -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
diff --git a/sys/compat/cloudabi32/cloudabi32_util.h b/sys/compat/cloudabi32/cloudabi32_util.h
index c08c91edfd0f..1661854a30f8 100644
--- a/sys/compat/cloudabi32/cloudabi32_util.h
+++ b/sys/compat/cloudabi32/cloudabi32_util.h
@@ -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 *,
diff --git a/sys/compat/cloudabi64/cloudabi64_module.c b/sys/compat/cloudabi64/cloudabi64_module.c
index fd0be086aac3..7459b026d8ec 100644
--- a/sys/compat/cloudabi64/cloudabi64_module.c
+++ b/sys/compat/cloudabi64/cloudabi64_module.c
@@ -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
diff --git a/sys/compat/cloudabi64/cloudabi64_util.h b/sys/compat/cloudabi64/cloudabi64_util.h
index 5d5063979032..59e93b37b1b6 100644
--- a/sys/compat/cloudabi64/cloudabi64_util.h
+++ b/sys/compat/cloudabi64/cloudabi64_util.h
@@ -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 *,
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
index ad0fd068a650..395e4e4a3668 100644
--- a/sys/compat/freebsd32/freebsd32_misc.c
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -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
diff --git a/sys/compat/freebsd32/freebsd32_util.h b/sys/compat/freebsd32/freebsd32_util.h
index cf6ff0d5a3ce..4da7c7029b6b 100644
--- a/sys/compat/freebsd32/freebsd32_util.h
+++ b/sys/compat/freebsd32/freebsd32_util.h
@@ -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);
diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c
index d36c10a8c071..787fb83c534b 100644
--- a/sys/i386/linux/linux_sysvec.c
+++ b/sys/i386/linux/linux_sysvec.c
@@ -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
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index 7cb073fc2cda..77b2960d1859 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -1323,12 +1323,13 @@ ret:
#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
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index a545068b8e2f..d8377674a712 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -672,7 +672,11 @@ interpret:
/*
* 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);
}
/*
diff --git a/sys/sys/imgact.h b/sys/sys/imgact.h
index 25393d8194c1..e9597086f7c1 100644
--- a/sys/sys/imgact.h
+++ b/sys/sys/imgact.h
@@ -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);
diff --git a/sys/sys/imgact_elf.h b/sys/sys/imgact_elf.h
index f3560f54882e..d56fd943f929 100644
--- a/sys/sys/imgact_elf.h
+++ b/sys/sys/imgact_elf.h
@@ -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 *);
diff --git a/sys/sys/sysent.h b/sys/sys/sysent.h
index 4c82c06c8476..cc3924ded7d8 100644
--- a/sys/sys/sysent.h
+++ b/sys/sys/sysent.h
@@ -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);