1/*- 2 * Copyright (c) 2015 Nuxi, https://nuxi.nl/ 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26#include <sys/cdefs.h> 27__FBSDID("$FreeBSD$"); 28 29#include <sys/param.h> 30#include <sys/imgact.h> 31#include <sys/kernel.h> 32#include <sys/module.h> 33#include <sys/proc.h> 34#include <sys/smp.h> 35#include <sys/sysctl.h> 36#include <sys/sysent.h> 37#include <sys/systm.h> 38 39#include <contrib/cloudabi/cloudabi32_types.h> 40 41#include <compat/cloudabi/cloudabi_util.h> 42 43#include <compat/cloudabi32/cloudabi32_util.h> 44 45extern char _binary_cloudabi32_vdso_o_start[]; 46extern char _binary_cloudabi32_vdso_o_end[]; 47 48register_t * 49cloudabi32_copyout_strings(struct image_params *imgp) 50{ 51 struct image_args *args; 52 uintptr_t begin; 53 size_t len; 54 55 /* Copy out program arguments. */ 56 args = imgp->args; 57 len = args->begin_envv - args->begin_argv; 58 begin = rounddown2(imgp->sysent->sv_usrstack - len, sizeof(register_t)); 59 copyout(args->begin_argv, (void *)begin, len); 60 return ((register_t *)begin); 61} 62 63int 64cloudabi32_fixup(register_t **stack_base, struct image_params *imgp) 65{ 66 char canarybuf[64], pidbuf[16]; 67 Elf32_Auxargs *args; 68 struct thread *td; 69 void *argdata, *canary, *pid; 70 size_t argdatalen; 71 int error; 72 73 /* 74 * CloudABI executables do not store the FreeBSD OS release 75 * number in their header. Set the OS release number to the 76 * latest version of FreeBSD, so that system calls behave as if 77 * called natively. 78 */ 79 td = curthread; 80 td->td_proc->p_osrel = __FreeBSD_version; 81 82 argdata = *stack_base; 83 84 /* Store canary for stack smashing protection. */ 85 arc4rand(canarybuf, sizeof(canarybuf), 0); 86 *stack_base -= howmany(sizeof(canarybuf), sizeof(register_t)); 87 canary = *stack_base; 88 error = copyout(canarybuf, canary, sizeof(canarybuf)); 89 if (error != 0) 90 return (error); 91 92 /* 93 * Generate a random UUID that identifies the process. Right now 94 * we don't store this UUID in the kernel. Ideally, it should be 95 * exposed through ps(1). 96 */ 97 arc4rand(pidbuf, sizeof(pidbuf), 0); 98 pidbuf[6] = (pidbuf[6] & 0x0f) | 0x40; 99 pidbuf[8] = (pidbuf[8] & 0x3f) | 0x80; 100 *stack_base -= howmany(sizeof(pidbuf), sizeof(register_t)); 101 pid = *stack_base; 102 error = copyout(pidbuf, pid, sizeof(pidbuf)); 103 if (error != 0) 104 return (error); 105 106 /* 107 * Compute length of program arguments. As the argument data is 108 * binary safe, we had to add a trailing null byte in 109 * exec_copyin_data_fds(). Undo this by reducing the length. 110 */ 111 args = (Elf32_Auxargs *)imgp->auxargs; 112 argdatalen = imgp->args->begin_envv - imgp->args->begin_argv; 113 if (argdatalen > 0) 114 --argdatalen; 115 116 /* Write out an auxiliary vector. */ 117 cloudabi32_auxv_t auxv[] = { 118#define VAL(type, val) { .a_type = (type), .a_val = (val) } 119#define PTR(type, ptr) { .a_type = (type), .a_ptr = (uintptr_t)(ptr) } 120 PTR(CLOUDABI_AT_ARGDATA, argdata), 121 VAL(CLOUDABI_AT_ARGDATALEN, argdatalen), 122 VAL(CLOUDABI_AT_BASE, args->base), 123 PTR(CLOUDABI_AT_CANARY, canary), 124 VAL(CLOUDABI_AT_CANARYLEN, sizeof(canarybuf)), 125 VAL(CLOUDABI_AT_NCPUS, mp_ncpus), 126 VAL(CLOUDABI_AT_PAGESZ, args->pagesz), 127 PTR(CLOUDABI_AT_PHDR, args->phdr), 128 VAL(CLOUDABI_AT_PHNUM, args->phnum), 129 PTR(CLOUDABI_AT_PID, pid), 130 PTR(CLOUDABI_AT_SYSINFO_EHDR, 131 imgp->proc->p_sysent->sv_shared_page_base), 132 VAL(CLOUDABI_AT_TID, td->td_tid), 133#undef VAL 134#undef PTR 135 { .a_type = CLOUDABI_AT_NULL }, 136 }; 137 *stack_base -= howmany(sizeof(auxv), sizeof(register_t)); 138 error = copyout(auxv, *stack_base, sizeof(auxv)); 139 if (error != 0) 140 return (error); 141 142 /* Reserve space for storing the TCB. */ 143 *stack_base -= howmany(sizeof(cloudabi32_tcb_t), sizeof(register_t)); 144 return (0); 145} 146 147static int 148cloudabi32_modevent(module_t mod, int type, void *data) 149{ 150 151 switch (type) { 152 case MOD_LOAD: 153 cloudabi_vdso_init(cloudabi32_brand.sysvec, 154 _binary_cloudabi32_vdso_o_start, 155 _binary_cloudabi32_vdso_o_end); 156 if (elf32_insert_brand_entry(&cloudabi32_brand) < 0) { 157 printf("Failed to add CloudABI ELF brand handler\n"); 158 return (EINVAL); 159 } 160 return (0); 161 case MOD_UNLOAD: 162 if (elf32_brand_inuse(&cloudabi32_brand)) 163 return (EBUSY); 164 if (elf32_remove_brand_entry(&cloudabi32_brand) < 0) { 165 printf("Failed to remove CloudABI ELF brand handler\n"); 166 return (EINVAL); 167 } 168 cloudabi_vdso_destroy(cloudabi32_brand.sysvec); 169 return (0); 170 default: 171 return (EOPNOTSUPP); 172 } 173} 174 175static moduledata_t cloudabi32_module = { 176 "cloudabi32", 177 cloudabi32_modevent, 178 NULL 179}; 180 181DECLARE_MODULE_TIED(cloudabi32, cloudabi32_module, SI_SUB_EXEC, SI_ORDER_ANY); 182MODULE_DEPEND(cloudabi32, cloudabi, 1, 1, 1); 183FEATURE(cloudabi32, "CloudABI 32bit support"); 184