linux(4): Deduplicate linux_copyout_strings().
It is still present in the 32-bit Linuxulator on amd64. MFC after: 1 week
This commit is contained in:
parent
9e550625f8
commit
6039e966ff
@ -115,8 +115,6 @@ extern const char *linux_syscallnames[];
|
|||||||
|
|
||||||
SET_DECLARE(linux_ioctl_handler_set, struct linux_ioctl_handler);
|
SET_DECLARE(linux_ioctl_handler_set, struct linux_ioctl_handler);
|
||||||
|
|
||||||
static int linux_copyout_strings(struct image_params *imgp,
|
|
||||||
uintptr_t *stack_base);
|
|
||||||
static bool linux_trans_osrel(const Elf_Note *note, int32_t *osrel);
|
static bool linux_trans_osrel(const Elf_Note *note, int32_t *osrel);
|
||||||
static void linux_vdso_install(const void *param);
|
static void linux_vdso_install(const void *param);
|
||||||
static void linux_vdso_deinstall(const void *param);
|
static void linux_vdso_deinstall(const void *param);
|
||||||
@ -268,132 +266,6 @@ linux_copyout_auxargs(struct image_params *imgp, uintptr_t base)
|
|||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Copy strings out to the new process address space, constructing new arg
|
|
||||||
* and env vector tables. Return a pointer to the base so that it can be used
|
|
||||||
* as the initial stack pointer.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
linux_copyout_strings(struct image_params *imgp, uintptr_t *stack_base)
|
|
||||||
{
|
|
||||||
int argc, envc, error;
|
|
||||||
char **vectp;
|
|
||||||
char *stringp;
|
|
||||||
uintptr_t destp, ustringp;
|
|
||||||
struct ps_strings *arginfo;
|
|
||||||
char canary[LINUX_AT_RANDOM_LEN];
|
|
||||||
size_t execpath_len;
|
|
||||||
struct proc *p;
|
|
||||||
|
|
||||||
p = imgp->proc;
|
|
||||||
arginfo = (struct ps_strings *)PROC_PS_STRINGS(p);
|
|
||||||
destp = (uintptr_t)arginfo;
|
|
||||||
|
|
||||||
if (imgp->execpath != NULL && imgp->auxargs != NULL) {
|
|
||||||
execpath_len = strlen(imgp->execpath) + 1;
|
|
||||||
destp -= execpath_len;
|
|
||||||
destp = rounddown2(destp, sizeof(void *));
|
|
||||||
imgp->execpathp = (void *)destp;
|
|
||||||
error = copyout(imgp->execpath, imgp->execpathp, execpath_len);
|
|
||||||
if (error != 0)
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Prepare the canary for SSP. */
|
|
||||||
arc4rand(canary, sizeof(canary), 0);
|
|
||||||
destp -= roundup(sizeof(canary), sizeof(void *));
|
|
||||||
imgp->canary = (void *)destp;
|
|
||||||
error = copyout(canary, imgp->canary, sizeof(canary));
|
|
||||||
if (error != 0)
|
|
||||||
return (error);
|
|
||||||
|
|
||||||
/* Allocate room for the argument and environment strings. */
|
|
||||||
destp -= ARG_MAX - imgp->args->stringspace;
|
|
||||||
destp = rounddown2(destp, sizeof(void *));
|
|
||||||
ustringp = destp;
|
|
||||||
|
|
||||||
if (imgp->auxargs) {
|
|
||||||
/*
|
|
||||||
* Allocate room on the stack for the ELF auxargs
|
|
||||||
* array. It has LINUX_AT_COUNT entries.
|
|
||||||
*/
|
|
||||||
destp -= LINUX_AT_COUNT * sizeof(Elf64_Auxinfo);
|
|
||||||
destp = rounddown2(destp, sizeof(void *));
|
|
||||||
}
|
|
||||||
|
|
||||||
vectp = (char **)destp;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Allocate room for the argv[] and env vectors including the
|
|
||||||
* terminating NULL pointers.
|
|
||||||
*/
|
|
||||||
vectp -= imgp->args->argc + 1 + imgp->args->envc + 1;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Starting with 2.24, glibc depends on a 16-byte stack alignment.
|
|
||||||
* One "long argc" will be prepended later.
|
|
||||||
*/
|
|
||||||
vectp = (char **)((((uintptr_t)vectp + 8) & ~0xF) - 8);
|
|
||||||
|
|
||||||
/* vectp also becomes our initial stack base. */
|
|
||||||
*stack_base = (uintptr_t)vectp;
|
|
||||||
|
|
||||||
stringp = imgp->args->begin_argv;
|
|
||||||
argc = imgp->args->argc;
|
|
||||||
envc = imgp->args->envc;
|
|
||||||
|
|
||||||
/* Copy out strings - arguments and environment. */
|
|
||||||
error = copyout(stringp, (void *)ustringp,
|
|
||||||
ARG_MAX - imgp->args->stringspace);
|
|
||||||
if (error != 0)
|
|
||||||
return (error);
|
|
||||||
|
|
||||||
/* Fill in "ps_strings" struct for ps, w, etc. */
|
|
||||||
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) {
|
|
||||||
if (suword(vectp++, ustringp) != 0)
|
|
||||||
return (EFAULT);
|
|
||||||
while (*stringp++ != 0)
|
|
||||||
ustringp++;
|
|
||||||
ustringp++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* A null vector table pointer separates the argp's from the envp's. */
|
|
||||||
if (suword(vectp++, 0) != 0)
|
|
||||||
return (EFAULT);
|
|
||||||
|
|
||||||
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) {
|
|
||||||
if (suword(vectp++, ustringp) != 0)
|
|
||||||
return (EFAULT);
|
|
||||||
while (*stringp++ != 0)
|
|
||||||
ustringp++;
|
|
||||||
ustringp++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The end of the vector table is a null pointer. */
|
|
||||||
if (suword(vectp, 0) != 0)
|
|
||||||
return (EFAULT);
|
|
||||||
|
|
||||||
if (imgp->auxargs) {
|
|
||||||
vectp++;
|
|
||||||
error = imgp->sysent->sv_copyout_auxargs(imgp,
|
|
||||||
(uintptr_t)vectp);
|
|
||||||
if (error != 0)
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reset registers to default values on exec.
|
* Reset registers to default values on exec.
|
||||||
*/
|
*/
|
||||||
@ -707,7 +579,7 @@ struct sysentvec elf_linux_sysvec = {
|
|||||||
.sv_psstringssz = sizeof(struct ps_strings),
|
.sv_psstringssz = sizeof(struct ps_strings),
|
||||||
.sv_stackprot = VM_PROT_ALL,
|
.sv_stackprot = VM_PROT_ALL,
|
||||||
.sv_copyout_auxargs = linux_copyout_auxargs,
|
.sv_copyout_auxargs = linux_copyout_auxargs,
|
||||||
.sv_copyout_strings = linux_copyout_strings,
|
.sv_copyout_strings = __linuxN(copyout_strings),
|
||||||
.sv_setregs = linux_exec_setregs,
|
.sv_setregs = linux_exec_setregs,
|
||||||
.sv_fixlimit = NULL,
|
.sv_fixlimit = NULL,
|
||||||
.sv_maxssiz = NULL,
|
.sv_maxssiz = NULL,
|
||||||
|
@ -105,10 +105,6 @@ extern const char *linux_syscallnames[];
|
|||||||
|
|
||||||
SET_DECLARE(linux_ioctl_handler_set, struct linux_ioctl_handler);
|
SET_DECLARE(linux_ioctl_handler_set, struct linux_ioctl_handler);
|
||||||
|
|
||||||
static int linux_copyout_strings(struct image_params *imgp,
|
|
||||||
uintptr_t *stack_base);
|
|
||||||
static int linux_elf_fixup(uintptr_t *stack_base,
|
|
||||||
struct image_params *iparams);
|
|
||||||
static bool linux_trans_osrel(const Elf_Note *note, int32_t *osrel);
|
static bool linux_trans_osrel(const Elf_Note *note, int32_t *osrel);
|
||||||
static void linux_vdso_install(const void *param);
|
static void linux_vdso_install(const void *param);
|
||||||
static void linux_vdso_deinstall(const void *param);
|
static void linux_vdso_deinstall(const void *param);
|
||||||
@ -127,7 +123,6 @@ LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE);
|
|||||||
/* DTrace probes */
|
/* DTrace probes */
|
||||||
LIN_SDT_PROBE_DEFINE0(sysvec, linux_exec_setregs, todo);
|
LIN_SDT_PROBE_DEFINE0(sysvec, linux_exec_setregs, todo);
|
||||||
LIN_SDT_PROBE_DEFINE0(sysvec, linux_copyout_auxargs, todo);
|
LIN_SDT_PROBE_DEFINE0(sysvec, linux_copyout_auxargs, todo);
|
||||||
LIN_SDT_PROBE_DEFINE0(sysvec, linux_elf_fixup, todo);
|
|
||||||
|
|
||||||
LINUX_VDSO_SYM_CHAR(linux_platform);
|
LINUX_VDSO_SYM_CHAR(linux_platform);
|
||||||
LINUX_VDSO_SYM_INTPTR(kern_timekeep_base);
|
LINUX_VDSO_SYM_INTPTR(kern_timekeep_base);
|
||||||
@ -225,140 +220,6 @@ linux_copyout_auxargs(struct image_params *imgp, uintptr_t base)
|
|||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
linux_elf_fixup(uintptr_t *stack_base, struct image_params *imgp)
|
|
||||||
{
|
|
||||||
|
|
||||||
LIN_SDT_PROBE0(sysvec, linux_elf_fixup, todo);
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copy strings out to the new process address space, constructing new arg
|
|
||||||
* and env vector tables. Return a pointer to the base so that it can be used
|
|
||||||
* as the initial stack pointer.
|
|
||||||
* LINUXTODO: deduplicate against other linuxulator archs
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
linux_copyout_strings(struct image_params *imgp, uintptr_t *stack_base)
|
|
||||||
{
|
|
||||||
char **vectp;
|
|
||||||
char *stringp;
|
|
||||||
uintptr_t destp, ustringp;
|
|
||||||
struct ps_strings *arginfo;
|
|
||||||
char canary[LINUX_AT_RANDOM_LEN];
|
|
||||||
size_t execpath_len;
|
|
||||||
struct proc *p;
|
|
||||||
int argc, envc, error;
|
|
||||||
|
|
||||||
p = imgp->proc;
|
|
||||||
arginfo = (struct ps_strings *)PROC_PS_STRINGS(p);
|
|
||||||
destp = (uintptr_t)arginfo;
|
|
||||||
|
|
||||||
if (imgp->execpath != NULL && imgp->auxargs != NULL) {
|
|
||||||
execpath_len = strlen(imgp->execpath) + 1;
|
|
||||||
destp -= execpath_len;
|
|
||||||
destp = rounddown2(destp, sizeof(void *));
|
|
||||||
imgp->execpathp = (void *)destp;
|
|
||||||
error = copyout(imgp->execpath, imgp->execpathp, execpath_len);
|
|
||||||
if (error != 0)
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Prepare the canary for SSP. */
|
|
||||||
arc4rand(canary, sizeof(canary), 0);
|
|
||||||
destp -= roundup(sizeof(canary), sizeof(void *));
|
|
||||||
imgp->canary = (void *)destp;
|
|
||||||
error = copyout(canary, imgp->canary, sizeof(canary));
|
|
||||||
if (error != 0)
|
|
||||||
return (error);
|
|
||||||
|
|
||||||
/* Allocate room for the argument and environment strings. */
|
|
||||||
destp -= ARG_MAX - imgp->args->stringspace;
|
|
||||||
destp = rounddown2(destp, sizeof(void *));
|
|
||||||
ustringp = destp;
|
|
||||||
|
|
||||||
if (imgp->auxargs) {
|
|
||||||
/*
|
|
||||||
* Allocate room on the stack for the ELF auxargs
|
|
||||||
* array. It has up to LINUX_AT_COUNT entries.
|
|
||||||
*/
|
|
||||||
destp -= LINUX_AT_COUNT * sizeof(Elf64_Auxinfo);
|
|
||||||
destp = rounddown2(destp, sizeof(void *));
|
|
||||||
}
|
|
||||||
|
|
||||||
vectp = (char **)destp;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Allocate room for argc and the argv[] and env vectors including the
|
|
||||||
* terminating NULL pointers.
|
|
||||||
*/
|
|
||||||
vectp -= 1 + imgp->args->argc + 1 + imgp->args->envc + 1;
|
|
||||||
vectp = (char **)STACKALIGN(vectp);
|
|
||||||
|
|
||||||
/* vectp also becomes our initial stack base. */
|
|
||||||
*stack_base = (uintptr_t)vectp;
|
|
||||||
|
|
||||||
stringp = imgp->args->begin_argv;
|
|
||||||
argc = imgp->args->argc;
|
|
||||||
envc = imgp->args->envc;
|
|
||||||
|
|
||||||
/* Copy out strings - arguments and environment. */
|
|
||||||
error = copyout(stringp, (void *)ustringp,
|
|
||||||
ARG_MAX - imgp->args->stringspace);
|
|
||||||
if (error != 0)
|
|
||||||
return (error);
|
|
||||||
|
|
||||||
/* Fill in "ps_strings" struct for ps, w, etc. */
|
|
||||||
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);
|
|
||||||
|
|
||||||
/* Fill in argument portion of vector table. */
|
|
||||||
for (; argc > 0; --argc) {
|
|
||||||
if (suword(vectp++, ustringp) != 0)
|
|
||||||
return (EFAULT);
|
|
||||||
while (*stringp++ != 0)
|
|
||||||
ustringp++;
|
|
||||||
ustringp++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* A null vector table pointer separates the argp's from the envp's. */
|
|
||||||
if (suword(vectp++, 0) != 0)
|
|
||||||
return (EFAULT);
|
|
||||||
|
|
||||||
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) {
|
|
||||||
if (suword(vectp++, ustringp) != 0)
|
|
||||||
return (EFAULT);
|
|
||||||
while (*stringp++ != 0)
|
|
||||||
ustringp++;
|
|
||||||
ustringp++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The end of the vector table is a null pointer. */
|
|
||||||
if (suword(vectp, 0) != 0)
|
|
||||||
return (EFAULT);
|
|
||||||
|
|
||||||
if (imgp->auxargs) {
|
|
||||||
vectp++;
|
|
||||||
error = imgp->sysent->sv_copyout_auxargs(imgp,
|
|
||||||
(uintptr_t)vectp);
|
|
||||||
if (error != 0)
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reset registers to default values on exec.
|
* Reset registers to default values on exec.
|
||||||
*/
|
*/
|
||||||
@ -554,7 +415,7 @@ linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
|
|||||||
struct sysentvec elf_linux_sysvec = {
|
struct sysentvec elf_linux_sysvec = {
|
||||||
.sv_size = LINUX_SYS_MAXSYSCALL,
|
.sv_size = LINUX_SYS_MAXSYSCALL,
|
||||||
.sv_table = linux_sysent,
|
.sv_table = linux_sysent,
|
||||||
.sv_fixup = linux_elf_fixup,
|
.sv_fixup = __elfN(freebsd_fixup),
|
||||||
.sv_sendsig = linux_rt_sendsig,
|
.sv_sendsig = linux_rt_sendsig,
|
||||||
.sv_sigcode = &_binary_linux_vdso_so_o_start,
|
.sv_sigcode = &_binary_linux_vdso_so_o_start,
|
||||||
.sv_szsigcode = &linux_szsigcode,
|
.sv_szsigcode = &linux_szsigcode,
|
||||||
@ -572,7 +433,7 @@ struct sysentvec elf_linux_sysvec = {
|
|||||||
.sv_psstringssz = sizeof(struct ps_strings),
|
.sv_psstringssz = sizeof(struct ps_strings),
|
||||||
.sv_stackprot = VM_PROT_READ | VM_PROT_WRITE,
|
.sv_stackprot = VM_PROT_READ | VM_PROT_WRITE,
|
||||||
.sv_copyout_auxargs = linux_copyout_auxargs,
|
.sv_copyout_auxargs = linux_copyout_auxargs,
|
||||||
.sv_copyout_strings = linux_copyout_strings,
|
.sv_copyout_strings = __linuxN(copyout_strings),
|
||||||
.sv_setregs = linux_exec_setregs,
|
.sv_setregs = linux_exec_setregs,
|
||||||
.sv_fixlimit = NULL,
|
.sv_fixlimit = NULL,
|
||||||
.sv_maxssiz = NULL,
|
.sv_maxssiz = NULL,
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
#include <sys/exec.h>
|
||||||
#include <sys/imgact.h>
|
#include <sys/imgact.h>
|
||||||
#include <sys/imgact_elf.h>
|
#include <sys/imgact_elf.h>
|
||||||
#include <sys/lock.h>
|
#include <sys/lock.h>
|
||||||
@ -50,6 +51,11 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <sys/procfs.h>
|
#include <sys/procfs.h>
|
||||||
#include <sys/reg.h>
|
#include <sys/reg.h>
|
||||||
#include <sys/sbuf.h>
|
#include <sys/sbuf.h>
|
||||||
|
#include <sys/sysent.h>
|
||||||
|
|
||||||
|
#include <vm/vm.h>
|
||||||
|
#include <vm/pmap.h>
|
||||||
|
#include <vm/vm_map.h>
|
||||||
|
|
||||||
#include <machine/elf.h>
|
#include <machine/elf.h>
|
||||||
|
|
||||||
@ -61,6 +67,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <machine/../linux/linux.h>
|
#include <machine/../linux/linux.h>
|
||||||
#endif
|
#endif
|
||||||
#include <compat/linux/linux_elf.h>
|
#include <compat/linux/linux_elf.h>
|
||||||
|
#include <compat/linux/linux_misc.h>
|
||||||
|
|
||||||
struct l_elf_siginfo {
|
struct l_elf_siginfo {
|
||||||
l_int si_signo;
|
l_int si_signo;
|
||||||
@ -312,3 +319,149 @@ __linuxN(note_nt_auxv)(void *arg, struct sbuf *sb, size_t *sizep)
|
|||||||
PRELE(p);
|
PRELE(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy strings out to the new process address space, constructing new arg
|
||||||
|
* and env vector tables. Return a pointer to the base so that it can be used
|
||||||
|
* as the initial stack pointer.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
__linuxN(copyout_strings)(struct image_params *imgp, uintptr_t *stack_base)
|
||||||
|
{
|
||||||
|
char canary[LINUX_AT_RANDOM_LEN];
|
||||||
|
char **vectp;
|
||||||
|
char *stringp;
|
||||||
|
uintptr_t destp, ustringp;
|
||||||
|
struct ps_strings *arginfo;
|
||||||
|
struct proc *p;
|
||||||
|
size_t execpath_len;
|
||||||
|
int argc, envc;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
p = imgp->proc;
|
||||||
|
destp = PROC_PS_STRINGS(p);
|
||||||
|
arginfo = imgp->ps_strings = (void *)destp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy the image path for the rtld.
|
||||||
|
*/
|
||||||
|
if (imgp->execpath != NULL && imgp->auxargs != NULL) {
|
||||||
|
execpath_len = strlen(imgp->execpath) + 1;
|
||||||
|
destp -= execpath_len;
|
||||||
|
destp = rounddown2(destp, sizeof(void *));
|
||||||
|
imgp->execpathp = (void *)destp;
|
||||||
|
error = copyout(imgp->execpath, imgp->execpathp, execpath_len);
|
||||||
|
if (error != 0)
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prepare the canary for SSP.
|
||||||
|
*/
|
||||||
|
arc4rand(canary, sizeof(canary), 0);
|
||||||
|
destp -= sizeof(canary);
|
||||||
|
imgp->canary = (void *)destp;
|
||||||
|
error = copyout(canary, imgp->canary, sizeof(canary));
|
||||||
|
if (error != 0)
|
||||||
|
return (error);
|
||||||
|
imgp->canarylen = sizeof(canary);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate room for the argument and environment strings.
|
||||||
|
*/
|
||||||
|
destp -= ARG_MAX - imgp->args->stringspace;
|
||||||
|
destp = rounddown2(destp, sizeof(void *));
|
||||||
|
ustringp = destp;
|
||||||
|
|
||||||
|
if (imgp->auxargs) {
|
||||||
|
/*
|
||||||
|
* Allocate room on the stack for the ELF auxargs
|
||||||
|
* array. It has up to LINUX_AT_COUNT entries.
|
||||||
|
*/
|
||||||
|
destp -= LINUX_AT_COUNT * sizeof(Elf_Auxinfo);
|
||||||
|
destp = rounddown2(destp, sizeof(void *));
|
||||||
|
}
|
||||||
|
|
||||||
|
vectp = (char **)destp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate room for the argv[] and env vectors including the
|
||||||
|
* terminating NULL pointers.
|
||||||
|
*/
|
||||||
|
vectp -= imgp->args->argc + 1 + imgp->args->envc + 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Starting with 2.24, glibc depends on a 16-byte stack alignment.
|
||||||
|
*/
|
||||||
|
vectp = (char **)((((uintptr_t)vectp + 8) & ~0xF) - 8);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* vectp also becomes our initial stack base
|
||||||
|
*/
|
||||||
|
*stack_base = (uintptr_t)vectp;
|
||||||
|
|
||||||
|
stringp = imgp->args->begin_argv;
|
||||||
|
argc = imgp->args->argc;
|
||||||
|
envc = imgp->args->envc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy out strings - arguments and environment.
|
||||||
|
*/
|
||||||
|
error = copyout(stringp, (void *)ustringp,
|
||||||
|
ARG_MAX - imgp->args->stringspace);
|
||||||
|
if (error != 0)
|
||||||
|
return (error);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fill in "ps_strings" struct for ps, w, etc.
|
||||||
|
*/
|
||||||
|
imgp->argv = vectp;
|
||||||
|
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) {
|
||||||
|
if (suword(vectp++, ustringp) != 0)
|
||||||
|
return (EFAULT);
|
||||||
|
while (*stringp++ != 0)
|
||||||
|
ustringp++;
|
||||||
|
ustringp++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* a null vector table pointer separates the argp's from the envp's */
|
||||||
|
if (suword(vectp++, 0) != 0)
|
||||||
|
return (EFAULT);
|
||||||
|
|
||||||
|
imgp->envv = vectp;
|
||||||
|
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) {
|
||||||
|
if (suword(vectp++, ustringp) != 0)
|
||||||
|
return (EFAULT);
|
||||||
|
while (*stringp++ != 0)
|
||||||
|
ustringp++;
|
||||||
|
ustringp++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* end of vector table is a null pointer */
|
||||||
|
if (suword(vectp, 0) != 0)
|
||||||
|
return (EFAULT);
|
||||||
|
|
||||||
|
if (imgp->auxargs) {
|
||||||
|
vectp++;
|
||||||
|
error = imgp->sysent->sv_copyout_auxargs(imgp,
|
||||||
|
(uintptr_t)vectp);
|
||||||
|
if (error != 0)
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
@ -38,5 +38,6 @@ struct note_info_list;
|
|||||||
|
|
||||||
void __linuxN(prepare_notes)(struct thread *, struct note_info_list *,
|
void __linuxN(prepare_notes)(struct thread *, struct note_info_list *,
|
||||||
size_t *);
|
size_t *);
|
||||||
|
int __linuxN(copyout_strings)(struct image_params *, uintptr_t *);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -111,8 +111,6 @@ static void linux_exec_setregs(struct thread *td,
|
|||||||
static void linux_exec_sysvec_init(void *param);
|
static void linux_exec_sysvec_init(void *param);
|
||||||
static int linux_on_exec_vmspace(struct proc *p,
|
static int linux_on_exec_vmspace(struct proc *p,
|
||||||
struct image_params *imgp);
|
struct image_params *imgp);
|
||||||
static int linux_copyout_strings(struct image_params *imgp,
|
|
||||||
uintptr_t *stack_base);
|
|
||||||
static void linux_set_fork_retval(struct thread *td);
|
static void linux_set_fork_retval(struct thread *td);
|
||||||
static bool linux_trans_osrel(const Elf_Note *note, int32_t *osrel);
|
static bool linux_trans_osrel(const Elf_Note *note, int32_t *osrel);
|
||||||
static void linux_vdso_install(const void *param);
|
static void linux_vdso_install(const void *param);
|
||||||
@ -201,124 +199,6 @@ linux_copyout_auxargs(struct image_params *imgp, uintptr_t base)
|
|||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Copied from kern/kern_exec.c
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
linux_copyout_strings(struct image_params *imgp, uintptr_t *stack_base)
|
|
||||||
{
|
|
||||||
int argc, envc, error;
|
|
||||||
char **vectp;
|
|
||||||
char *stringp;
|
|
||||||
uintptr_t destp, ustringp;
|
|
||||||
struct ps_strings *arginfo;
|
|
||||||
char canary[LINUX_AT_RANDOM_LEN];
|
|
||||||
size_t execpath_len;
|
|
||||||
struct proc *p;
|
|
||||||
|
|
||||||
p = imgp->proc;
|
|
||||||
arginfo = (struct ps_strings *)PROC_PS_STRINGS(p);
|
|
||||||
destp = (uintptr_t)arginfo;
|
|
||||||
|
|
||||||
if (imgp->execpath != NULL && imgp->auxargs != NULL) {
|
|
||||||
execpath_len = strlen(imgp->execpath) + 1;
|
|
||||||
destp -= execpath_len;
|
|
||||||
destp = rounddown2(destp, sizeof(void *));
|
|
||||||
imgp->execpathp = (void *)destp;
|
|
||||||
error = copyout(imgp->execpath, imgp->execpathp, execpath_len);
|
|
||||||
if (error != 0)
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Prepare the canary for SSP. */
|
|
||||||
arc4rand(canary, sizeof(canary), 0);
|
|
||||||
destp -= roundup(sizeof(canary), sizeof(void *));
|
|
||||||
imgp->canary = (void *)destp;
|
|
||||||
error = copyout(canary, imgp->canary, sizeof(canary));
|
|
||||||
if (error != 0)
|
|
||||||
return (error);
|
|
||||||
|
|
||||||
/* Allocate room for the argument and environment strings. */
|
|
||||||
destp -= ARG_MAX - imgp->args->stringspace;
|
|
||||||
destp = rounddown2(destp, sizeof(void *));
|
|
||||||
ustringp = destp;
|
|
||||||
|
|
||||||
if (imgp->auxargs) {
|
|
||||||
/*
|
|
||||||
* Allocate room on the stack for the ELF auxargs
|
|
||||||
* array. It has LINUX_AT_COUNT entries.
|
|
||||||
*/
|
|
||||||
destp -= LINUX_AT_COUNT * sizeof(Elf32_Auxinfo);
|
|
||||||
destp = rounddown2(destp, sizeof(void *));
|
|
||||||
}
|
|
||||||
|
|
||||||
vectp = (char **)destp;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Allocate room for the argv[] and env vectors including the
|
|
||||||
* terminating NULL pointers.
|
|
||||||
*/
|
|
||||||
vectp -= imgp->args->argc + 1 + imgp->args->envc + 1;
|
|
||||||
|
|
||||||
/* vectp also becomes our initial stack base. */
|
|
||||||
*stack_base = (uintptr_t)vectp;
|
|
||||||
|
|
||||||
stringp = imgp->args->begin_argv;
|
|
||||||
argc = imgp->args->argc;
|
|
||||||
envc = imgp->args->envc;
|
|
||||||
|
|
||||||
/* Copy out strings - arguments and environment. */
|
|
||||||
error = copyout(stringp, (void *)ustringp,
|
|
||||||
ARG_MAX - imgp->args->stringspace);
|
|
||||||
if (error != 0)
|
|
||||||
return (error);
|
|
||||||
|
|
||||||
/* Fill in "ps_strings" struct for ps, w, etc. */
|
|
||||||
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) {
|
|
||||||
if (suword(vectp++, ustringp) != 0)
|
|
||||||
return (EFAULT);
|
|
||||||
while (*stringp++ != 0)
|
|
||||||
ustringp++;
|
|
||||||
ustringp++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* A null vector table pointer separates the argp's from the envp's. */
|
|
||||||
if (suword(vectp++, 0) != 0)
|
|
||||||
return (EFAULT);
|
|
||||||
|
|
||||||
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) {
|
|
||||||
if (suword(vectp++, ustringp) != 0)
|
|
||||||
return (EFAULT);
|
|
||||||
while (*stringp++ != 0)
|
|
||||||
ustringp++;
|
|
||||||
ustringp++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The end of the vector table is a null pointer. */
|
|
||||||
if (suword(vectp, 0) != 0)
|
|
||||||
return (EFAULT);
|
|
||||||
|
|
||||||
if (imgp->auxargs) {
|
|
||||||
vectp++;
|
|
||||||
error = imgp->sysent->sv_copyout_auxargs(imgp,
|
|
||||||
(uintptr_t)vectp);
|
|
||||||
if (error != 0)
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
|
linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
|
||||||
{
|
{
|
||||||
@ -804,7 +684,7 @@ struct sysentvec elf_linux_sysvec = {
|
|||||||
.sv_psstringssz = sizeof(struct ps_strings),
|
.sv_psstringssz = sizeof(struct ps_strings),
|
||||||
.sv_stackprot = VM_PROT_ALL,
|
.sv_stackprot = VM_PROT_ALL,
|
||||||
.sv_copyout_auxargs = linux_copyout_auxargs,
|
.sv_copyout_auxargs = linux_copyout_auxargs,
|
||||||
.sv_copyout_strings = linux_copyout_strings,
|
.sv_copyout_strings = __linuxN(copyout_strings),
|
||||||
.sv_setregs = linux_exec_setregs,
|
.sv_setregs = linux_exec_setregs,
|
||||||
.sv_fixlimit = NULL,
|
.sv_fixlimit = NULL,
|
||||||
.sv_maxssiz = NULL,
|
.sv_maxssiz = NULL,
|
||||||
|
Loading…
Reference in New Issue
Block a user