1/* 2 * Copyright (c) 1993, David Greenman 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 *
| 1/* 2 * Copyright (c) 1993, David Greenman 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 *
|
26 * $FreeBSD: head/sys/kern/imgact_aout.c 102808 2002-09-01 21:41:24Z jake $
| 26 * $FreeBSD: head/sys/kern/imgact_aout.c 103047 2002-09-07 01:23:51Z peter $
|
27 */ 28 29#include "opt_kstack_pages.h" 30 31#include <sys/param.h> 32#include <sys/exec.h> 33#include <sys/fcntl.h> 34#include <sys/imgact.h> 35#include <sys/imgact_aout.h> 36#include <sys/kernel.h> 37#include <sys/lock.h> 38#include <sys/mutex.h> 39#include <sys/namei.h> 40#include <sys/pioctl.h> 41#include <sys/proc.h> 42#include <sys/resourcevar.h> 43#include <sys/systm.h> 44#include <sys/signalvar.h> 45#include <sys/stat.h> 46#include <sys/sysent.h> 47#include <sys/syscall.h> 48#include <sys/vnode.h> 49#include <sys/user.h> 50 51#include <machine/md_var.h>
| 27 */ 28 29#include "opt_kstack_pages.h" 30 31#include <sys/param.h> 32#include <sys/exec.h> 33#include <sys/fcntl.h> 34#include <sys/imgact.h> 35#include <sys/imgact_aout.h> 36#include <sys/kernel.h> 37#include <sys/lock.h> 38#include <sys/mutex.h> 39#include <sys/namei.h> 40#include <sys/pioctl.h> 41#include <sys/proc.h> 42#include <sys/resourcevar.h> 43#include <sys/systm.h> 44#include <sys/signalvar.h> 45#include <sys/stat.h> 46#include <sys/sysent.h> 47#include <sys/syscall.h> 48#include <sys/vnode.h> 49#include <sys/user.h> 50 51#include <machine/md_var.h>
|
| 52#include <machine/frame.h>
|
52 53#include <vm/vm.h> 54#include <vm/vm_param.h> 55#include <vm/pmap.h> 56#include <vm/vm_map.h> 57#include <vm/vm_object.h> 58 59static int exec_aout_imgact(struct image_params *imgp); 60static int aout_fixup(register_t **stack_base, struct image_params *imgp); 61 62struct sysentvec aout_sysvec = { 63 SYS_MAXSYSCALL, 64 sysent, 65 0, 66 0, 67 NULL, 68 0, 69 NULL, 70 NULL, 71 aout_fixup, 72 sendsig, 73 sigcode, 74 &szsigcode, 75 NULL, 76 "FreeBSD a.out", 77 aout_coredump, 78 NULL, 79 MINSIGSTKSZ, 80 PAGE_SIZE, 81 VM_MIN_ADDRESS, 82 VM_MAXUSER_ADDRESS, 83 USRSTACK, 84 PS_STRINGS, 85 VM_PROT_ALL, 86 exec_copyout_strings, 87 exec_setregs 88}; 89 90static int 91aout_fixup(stack_base, imgp) 92 register_t **stack_base; 93 struct image_params *imgp; 94{ 95 96 return (suword(--(*stack_base), imgp->argc)); 97} 98 99static int 100exec_aout_imgact(imgp) 101 struct image_params *imgp; 102{ 103 const struct exec *a_out = (const struct exec *) imgp->image_header; 104 struct vmspace *vmspace; 105 struct vnode *vp; 106 vm_map_t map; 107 vm_object_t object; 108 vm_offset_t text_end, data_end; 109 unsigned long virtual_offset; 110 unsigned long file_offset; 111 unsigned long bss_size; 112 int error; 113 114 GIANT_REQUIRED; 115 116 /* 117 * Linux and *BSD binaries look very much alike, 118 * only the machine id is different: 119 * 0x64 for Linux, 0x86 for *BSD, 0x00 for BSDI. 120 * NetBSD is in network byte order.. ugh. 121 */ 122 if (((a_out->a_magic >> 16) & 0xff) != 0x86 && 123 ((a_out->a_magic >> 16) & 0xff) != 0 && 124 ((((int)ntohl(a_out->a_magic)) >> 16) & 0xff) != 0x86) 125 return -1; 126 127 /* 128 * Set file/virtual offset based on a.out variant. 129 * We do two cases: host byte order and network byte order 130 * (for NetBSD compatibility) 131 */ 132 switch ((int)(a_out->a_magic & 0xffff)) { 133 case ZMAGIC: 134 virtual_offset = 0; 135 if (a_out->a_text) { 136 file_offset = PAGE_SIZE; 137 } else { 138 /* Bill's "screwball mode" */ 139 file_offset = 0; 140 } 141 break; 142 case QMAGIC: 143 virtual_offset = PAGE_SIZE; 144 file_offset = 0; 145 /* Pass PS_STRINGS for BSD/OS binaries only. */ 146 if (N_GETMID(*a_out) == MID_ZERO) 147 imgp->ps_strings = PS_STRINGS; 148 break; 149 default: 150 /* NetBSD compatibility */ 151 switch ((int)(ntohl(a_out->a_magic) & 0xffff)) { 152 case ZMAGIC: 153 case QMAGIC: 154 virtual_offset = PAGE_SIZE; 155 file_offset = 0; 156 break; 157 default: 158 return (-1); 159 } 160 } 161 162 bss_size = roundup(a_out->a_bss, PAGE_SIZE); 163 164 /* 165 * Check various fields in header for validity/bounds. 166 */ 167 if (/* entry point must lay with text region */ 168 a_out->a_entry < virtual_offset || 169 a_out->a_entry >= virtual_offset + a_out->a_text || 170 171 /* text and data size must each be page rounded */ 172 a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK) 173 return (-1); 174 175 /* text + data can't exceed file size */ 176 if (a_out->a_data + a_out->a_text > imgp->attr->va_size) 177 return (EFAULT); 178 179 /* 180 * text/data/bss must not exceed limits 181 */ 182 mtx_assert(&Giant, MA_OWNED); 183 if (/* text can't exceed maximum text size */ 184 a_out->a_text > maxtsiz || 185 186 /* data + bss can't exceed rlimit */ 187 a_out->a_data + bss_size > 188 imgp->proc->p_rlimit[RLIMIT_DATA].rlim_cur) 189 return (ENOMEM); 190 191 /* copy in arguments and/or environment from old process */ 192 error = exec_extract_strings(imgp); 193 if (error) 194 return (error); 195 196 /* 197 * Destroy old process VM and create a new one (with a new stack) 198 */ 199 exec_new_vmspace(imgp, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS, USRSTACK); 200 201 /* 202 * The vm space can be changed by exec_new_vmspace 203 */ 204 vmspace = imgp->proc->p_vmspace; 205 206 vp = imgp->vp; 207 object = imgp->object; 208 map = &vmspace->vm_map; 209 vm_map_lock(map); 210 vm_object_reference(object); 211 212 text_end = virtual_offset + a_out->a_text; 213 error = vm_map_insert(map, object, 214 file_offset, 215 virtual_offset, text_end, 216 VM_PROT_READ | VM_PROT_EXECUTE, VM_PROT_ALL, 217 MAP_COPY_ON_WRITE | MAP_PREFAULT); 218 if (error) { 219 vm_map_unlock(map); 220 return (error); 221 } 222 data_end = text_end + a_out->a_data; 223 if (a_out->a_data) { 224 vm_object_reference(object); 225 error = vm_map_insert(map, object, 226 file_offset + a_out->a_text, 227 text_end, data_end, 228 VM_PROT_ALL, VM_PROT_ALL, 229 MAP_COPY_ON_WRITE | MAP_PREFAULT); 230 if (error) { 231 vm_map_unlock(map); 232 return (error); 233 } 234 } 235 236 if (bss_size) { 237 error = vm_map_insert(map, NULL, 0, 238 data_end, data_end + bss_size, 239 VM_PROT_ALL, VM_PROT_ALL, 0); 240 if (error) { 241 vm_map_unlock(map); 242 return (error); 243 } 244 } 245 vm_map_unlock(map); 246 247 /* Fill in process VM information */ 248 vmspace->vm_tsize = a_out->a_text >> PAGE_SHIFT; 249 vmspace->vm_dsize = (a_out->a_data + bss_size) >> PAGE_SHIFT; 250 vmspace->vm_taddr = (caddr_t) (uintptr_t) virtual_offset; 251 vmspace->vm_daddr = (caddr_t) (uintptr_t) 252 (virtual_offset + a_out->a_text); 253 254 /* Fill in image_params */ 255 imgp->interpreted = 0; 256 imgp->entry_addr = a_out->a_entry; 257 258 imgp->proc->p_sysent = &aout_sysvec; 259 260 return (0); 261} 262 263/* 264 * Dump core, into a file named as described in the comments for 265 * expand_name(), unless the process was setuid/setgid. 266 */ 267int 268aout_coredump(td, vp, limit) 269 register struct thread *td; 270 register struct vnode *vp; 271 off_t limit; 272{ 273 struct proc *p = td->td_proc; 274 register struct ucred *cred = td->td_ucred; 275 register struct vmspace *vm = p->p_vmspace;
| 53 54#include <vm/vm.h> 55#include <vm/vm_param.h> 56#include <vm/pmap.h> 57#include <vm/vm_map.h> 58#include <vm/vm_object.h> 59 60static int exec_aout_imgact(struct image_params *imgp); 61static int aout_fixup(register_t **stack_base, struct image_params *imgp); 62 63struct sysentvec aout_sysvec = { 64 SYS_MAXSYSCALL, 65 sysent, 66 0, 67 0, 68 NULL, 69 0, 70 NULL, 71 NULL, 72 aout_fixup, 73 sendsig, 74 sigcode, 75 &szsigcode, 76 NULL, 77 "FreeBSD a.out", 78 aout_coredump, 79 NULL, 80 MINSIGSTKSZ, 81 PAGE_SIZE, 82 VM_MIN_ADDRESS, 83 VM_MAXUSER_ADDRESS, 84 USRSTACK, 85 PS_STRINGS, 86 VM_PROT_ALL, 87 exec_copyout_strings, 88 exec_setregs 89}; 90 91static int 92aout_fixup(stack_base, imgp) 93 register_t **stack_base; 94 struct image_params *imgp; 95{ 96 97 return (suword(--(*stack_base), imgp->argc)); 98} 99 100static int 101exec_aout_imgact(imgp) 102 struct image_params *imgp; 103{ 104 const struct exec *a_out = (const struct exec *) imgp->image_header; 105 struct vmspace *vmspace; 106 struct vnode *vp; 107 vm_map_t map; 108 vm_object_t object; 109 vm_offset_t text_end, data_end; 110 unsigned long virtual_offset; 111 unsigned long file_offset; 112 unsigned long bss_size; 113 int error; 114 115 GIANT_REQUIRED; 116 117 /* 118 * Linux and *BSD binaries look very much alike, 119 * only the machine id is different: 120 * 0x64 for Linux, 0x86 for *BSD, 0x00 for BSDI. 121 * NetBSD is in network byte order.. ugh. 122 */ 123 if (((a_out->a_magic >> 16) & 0xff) != 0x86 && 124 ((a_out->a_magic >> 16) & 0xff) != 0 && 125 ((((int)ntohl(a_out->a_magic)) >> 16) & 0xff) != 0x86) 126 return -1; 127 128 /* 129 * Set file/virtual offset based on a.out variant. 130 * We do two cases: host byte order and network byte order 131 * (for NetBSD compatibility) 132 */ 133 switch ((int)(a_out->a_magic & 0xffff)) { 134 case ZMAGIC: 135 virtual_offset = 0; 136 if (a_out->a_text) { 137 file_offset = PAGE_SIZE; 138 } else { 139 /* Bill's "screwball mode" */ 140 file_offset = 0; 141 } 142 break; 143 case QMAGIC: 144 virtual_offset = PAGE_SIZE; 145 file_offset = 0; 146 /* Pass PS_STRINGS for BSD/OS binaries only. */ 147 if (N_GETMID(*a_out) == MID_ZERO) 148 imgp->ps_strings = PS_STRINGS; 149 break; 150 default: 151 /* NetBSD compatibility */ 152 switch ((int)(ntohl(a_out->a_magic) & 0xffff)) { 153 case ZMAGIC: 154 case QMAGIC: 155 virtual_offset = PAGE_SIZE; 156 file_offset = 0; 157 break; 158 default: 159 return (-1); 160 } 161 } 162 163 bss_size = roundup(a_out->a_bss, PAGE_SIZE); 164 165 /* 166 * Check various fields in header for validity/bounds. 167 */ 168 if (/* entry point must lay with text region */ 169 a_out->a_entry < virtual_offset || 170 a_out->a_entry >= virtual_offset + a_out->a_text || 171 172 /* text and data size must each be page rounded */ 173 a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK) 174 return (-1); 175 176 /* text + data can't exceed file size */ 177 if (a_out->a_data + a_out->a_text > imgp->attr->va_size) 178 return (EFAULT); 179 180 /* 181 * text/data/bss must not exceed limits 182 */ 183 mtx_assert(&Giant, MA_OWNED); 184 if (/* text can't exceed maximum text size */ 185 a_out->a_text > maxtsiz || 186 187 /* data + bss can't exceed rlimit */ 188 a_out->a_data + bss_size > 189 imgp->proc->p_rlimit[RLIMIT_DATA].rlim_cur) 190 return (ENOMEM); 191 192 /* copy in arguments and/or environment from old process */ 193 error = exec_extract_strings(imgp); 194 if (error) 195 return (error); 196 197 /* 198 * Destroy old process VM and create a new one (with a new stack) 199 */ 200 exec_new_vmspace(imgp, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS, USRSTACK); 201 202 /* 203 * The vm space can be changed by exec_new_vmspace 204 */ 205 vmspace = imgp->proc->p_vmspace; 206 207 vp = imgp->vp; 208 object = imgp->object; 209 map = &vmspace->vm_map; 210 vm_map_lock(map); 211 vm_object_reference(object); 212 213 text_end = virtual_offset + a_out->a_text; 214 error = vm_map_insert(map, object, 215 file_offset, 216 virtual_offset, text_end, 217 VM_PROT_READ | VM_PROT_EXECUTE, VM_PROT_ALL, 218 MAP_COPY_ON_WRITE | MAP_PREFAULT); 219 if (error) { 220 vm_map_unlock(map); 221 return (error); 222 } 223 data_end = text_end + a_out->a_data; 224 if (a_out->a_data) { 225 vm_object_reference(object); 226 error = vm_map_insert(map, object, 227 file_offset + a_out->a_text, 228 text_end, data_end, 229 VM_PROT_ALL, VM_PROT_ALL, 230 MAP_COPY_ON_WRITE | MAP_PREFAULT); 231 if (error) { 232 vm_map_unlock(map); 233 return (error); 234 } 235 } 236 237 if (bss_size) { 238 error = vm_map_insert(map, NULL, 0, 239 data_end, data_end + bss_size, 240 VM_PROT_ALL, VM_PROT_ALL, 0); 241 if (error) { 242 vm_map_unlock(map); 243 return (error); 244 } 245 } 246 vm_map_unlock(map); 247 248 /* Fill in process VM information */ 249 vmspace->vm_tsize = a_out->a_text >> PAGE_SHIFT; 250 vmspace->vm_dsize = (a_out->a_data + bss_size) >> PAGE_SHIFT; 251 vmspace->vm_taddr = (caddr_t) (uintptr_t) virtual_offset; 252 vmspace->vm_daddr = (caddr_t) (uintptr_t) 253 (virtual_offset + a_out->a_text); 254 255 /* Fill in image_params */ 256 imgp->interpreted = 0; 257 imgp->entry_addr = a_out->a_entry; 258 259 imgp->proc->p_sysent = &aout_sysvec; 260 261 return (0); 262} 263 264/* 265 * Dump core, into a file named as described in the comments for 266 * expand_name(), unless the process was setuid/setgid. 267 */ 268int 269aout_coredump(td, vp, limit) 270 register struct thread *td; 271 register struct vnode *vp; 272 off_t limit; 273{ 274 struct proc *p = td->td_proc; 275 register struct ucred *cred = td->td_ucred; 276 register struct vmspace *vm = p->p_vmspace;
|
| 277 caddr_t tempuser;
|
276 int error; 277 278 if (ctob((UAREA_PAGES + KSTACK_PAGES) 279 + vm->vm_dsize + vm->vm_ssize) >= limit) 280 return (EFAULT);
| 278 int error; 279 280 if (ctob((UAREA_PAGES + KSTACK_PAGES) 281 + vm->vm_dsize + vm->vm_ssize) >= limit) 282 return (EFAULT);
|
| 283 tempuser = malloc(ctob(UAREA_PAGES + KSTACK_PAGES), M_TEMP, 284 M_WAITOK | M_ZERO); 285 if (tempuser == NULL) 286 return (ENOMEM); 287 bcopy(p->p_uarea, tempuser, sizeof(struct user)); 288 bcopy(td->td_frame, 289 tempuser + ctob(UAREA_PAGES) + 290 ((caddr_t) td->td_frame - (caddr_t) td->td_kstack), 291 sizeof(struct trapframe));
|
281 PROC_LOCK(p); 282 fill_kinfo_proc(p, &p->p_uarea->u_kproc); 283 PROC_UNLOCK(p);
| 292 PROC_LOCK(p); 293 fill_kinfo_proc(p, &p->p_uarea->u_kproc); 294 PROC_UNLOCK(p);
|
284 error = cpu_coredump(td, vp, cred);
| 295 error = vn_rdwr(UIO_WRITE, vp, (caddr_t) tempuser, 296 ctob(UAREA_PAGES + KSTACK_PAGES), 297 (off_t)0, UIO_SYSSPACE, IO_UNIT, cred, NOCRED, 298 (int *)NULL, td); 299 free(tempuser, M_TEMP);
|
285 if (error == 0) 286 error = vn_rdwr(UIO_WRITE, vp, vm->vm_daddr, 287 (int)ctob(vm->vm_dsize), 288 (off_t)ctob(UAREA_PAGES + KSTACK_PAGES), UIO_USERSPACE, 289 IO_UNIT | IO_DIRECT, cred, NOCRED, (int *) NULL, td); 290 if (error == 0) 291 error = vn_rdwr_inchunks(UIO_WRITE, vp, 292 (caddr_t) trunc_page(USRSTACK - ctob(vm->vm_ssize)), 293 round_page(ctob(vm->vm_ssize)), 294 (off_t)ctob(UAREA_PAGES + KSTACK_PAGES) + 295 ctob(vm->vm_dsize), UIO_USERSPACE, 296 IO_UNIT | IO_DIRECT, cred, NOCRED, (int *) NULL, td); 297 return (error); 298} 299 300/* 301 * Tell kern_execve.c about it, with a little help from the linker. 302 */ 303static struct execsw aout_execsw = { exec_aout_imgact, "a.out" }; 304EXEC_SET(aout, aout_execsw);
| 300 if (error == 0) 301 error = vn_rdwr(UIO_WRITE, vp, vm->vm_daddr, 302 (int)ctob(vm->vm_dsize), 303 (off_t)ctob(UAREA_PAGES + KSTACK_PAGES), UIO_USERSPACE, 304 IO_UNIT | IO_DIRECT, cred, NOCRED, (int *) NULL, td); 305 if (error == 0) 306 error = vn_rdwr_inchunks(UIO_WRITE, vp, 307 (caddr_t) trunc_page(USRSTACK - ctob(vm->vm_ssize)), 308 round_page(ctob(vm->vm_ssize)), 309 (off_t)ctob(UAREA_PAGES + KSTACK_PAGES) + 310 ctob(vm->vm_dsize), UIO_USERSPACE, 311 IO_UNIT | IO_DIRECT, cred, NOCRED, (int *) NULL, td); 312 return (error); 313} 314 315/* 316 * Tell kern_execve.c about it, with a little help from the linker. 317 */ 318static struct execsw aout_execsw = { exec_aout_imgact, "a.out" }; 319EXEC_SET(aout, aout_execsw);
|