From 7fb0afec66034c72011184b7e167248af15d3e68 Mon Sep 17 00:00:00 2001 From: ed Date: Thu, 22 Oct 2015 09:07:53 +0000 Subject: Refactoring: move out generic bits from cloudabi64_sysvec.c. In order to make it easier to support CloudABI on ARM64, move out all of the bits from the AMD64 cloudabi_sysvec.c into a new file cloudabi_module.c that would otherwise remain identical. This reduces the AMD64 specific code to just ~160 lines. Reviewed by: kib Differential Revision: https://reviews.freebsd.org/D3974 --- sys/compat/cloudabi64/cloudabi64_module.c | 148 ++++++++++++++++++++++++++++++ sys/compat/cloudabi64/cloudabi64_util.h | 10 ++ 2 files changed, 158 insertions(+) create mode 100644 sys/compat/cloudabi64/cloudabi64_module.c (limited to 'sys/compat') diff --git a/sys/compat/cloudabi64/cloudabi64_module.c b/sys/compat/cloudabi64/cloudabi64_module.c new file mode 100644 index 0000000..ca8ecf4 --- /dev/null +++ b/sys/compat/cloudabi64/cloudabi64_module.c @@ -0,0 +1,148 @@ +/*- + * Copyright (c) 2015 Nuxi, https://nuxi.nl/ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +register_t * +cloudabi64_copyout_strings(struct image_params *imgp) +{ + struct image_args *args; + uintptr_t begin; + size_t len; + + /* Copy out program arguments. */ + args = imgp->args; + len = args->begin_envv - args->begin_argv; + begin = rounddown2(imgp->sysent->sv_usrstack - len, sizeof(register_t)); + copyout(args->begin_argv, (void *)begin, len); + return ((register_t *)begin); +} + +int +cloudabi64_fixup(register_t **stack_base, struct image_params *imgp) +{ + char canarybuf[64]; + Elf64_Auxargs *args; + struct thread *td; + void *argdata, *canary; + size_t argdatalen; + int error; + + /* + * CloudABI executables do not store the FreeBSD OS release + * number in their header. Set the OS release number to the + * latest version of FreeBSD, so that system calls behave as if + * called natively. + */ + td = curthread; + td->td_proc->p_osrel = __FreeBSD_version; + + /* Store canary for stack smashing protection. */ + argdata = *stack_base; + arc4rand(canarybuf, sizeof(canarybuf), 0); + *stack_base -= howmany(sizeof(canarybuf), sizeof(register_t)); + canary = *stack_base; + error = copyout(canarybuf, canary, sizeof(canarybuf)); + if (error != 0) + return (error); + + /* + * Compute length of program arguments. As the argument data is + * binary safe, we had to add a trailing null byte in + * exec_copyin_data_fds(). Undo this by reducing the length. + */ + args = (Elf64_Auxargs *)imgp->auxargs; + argdatalen = imgp->args->begin_envv - imgp->args->begin_argv; + if (argdatalen > 0) + --argdatalen; + + /* Write out an auxiliary vector. */ + cloudabi64_auxv_t auxv[] = { +#define VAL(type, val) { .a_type = (type), .a_val = (val) } +#define PTR(type, ptr) { .a_type = (type), .a_ptr = (uintptr_t)(ptr) } + PTR(CLOUDABI_AT_ARGDATA, argdata), + VAL(CLOUDABI_AT_ARGDATALEN, argdatalen), + PTR(CLOUDABI_AT_CANARY, canary), + VAL(CLOUDABI_AT_CANARYLEN, sizeof(canarybuf)), + VAL(CLOUDABI_AT_NCPUS, mp_ncpus), + VAL(CLOUDABI_AT_PAGESZ, args->pagesz), + PTR(CLOUDABI_AT_PHDR, args->phdr), + VAL(CLOUDABI_AT_PHNUM, args->phnum), + VAL(CLOUDABI_AT_TID, td->td_tid), +#undef VAL +#undef PTR + { .a_type = CLOUDABI_AT_NULL }, + }; + *stack_base -= howmany(sizeof(auxv), sizeof(register_t)); + return (copyout(auxv, *stack_base, sizeof(auxv))); +} + +static int +cloudabi64_modevent(module_t mod, int type, void *data) +{ + + switch (type) { + case MOD_LOAD: + if (elf64_insert_brand_entry(&cloudabi64_brand) < 0) { + printf("Failed to add CloudABI ELF brand handler\n"); + return (EINVAL); + } + return (0); + case MOD_UNLOAD: + if (elf64_brand_inuse(&cloudabi64_brand)) + return (EBUSY); + if (elf64_remove_brand_entry(&cloudabi64_brand) < 0) { + printf("Failed to remove CloudABI ELF brand handler\n"); + return (EINVAL); + } + return (0); + default: + return (EOPNOTSUPP); + } +} + +static moduledata_t cloudabi64_module = { + "cloudabi64", + cloudabi64_modevent, + NULL +}; + +DECLARE_MODULE_TIED(cloudabi64, cloudabi64_module, SI_SUB_EXEC, SI_ORDER_ANY); +MODULE_DEPEND(cloudabi64, cloudabi, 1, 1, 1); +FEATURE(cloudabi64, "CloudABI 64bit support"); diff --git a/sys/compat/cloudabi64/cloudabi64_util.h b/sys/compat/cloudabi64/cloudabi64_util.h index c56d4cc..180a01e 100644 --- a/sys/compat/cloudabi64/cloudabi64_util.h +++ b/sys/compat/cloudabi64/cloudabi64_util.h @@ -28,10 +28,20 @@ #ifndef _CLOUDABI64_UTIL_H_ #define _CLOUDABI64_UTIL_H_ +#include +#include + #include +struct image_params; struct thread; +extern Elf64_Brandinfo cloudabi64_brand; + +/* Stack initialization during process execution. */ +register_t *cloudabi64_copyout_strings(struct image_params *); +int cloudabi64_fixup(register_t **, struct image_params *); + void cloudabi64_thread_setregs(struct thread *, const cloudabi64_threadattr_t *); -- cgit v1.1