1 /* 2 * Copyright (c) 2003 Matthew Dillon <dillon@backplane.com> 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 * $DragonFly: src/sys/kern/imgact_resident.c,v 1.2 2004/01/20 21:03:23 dillon Exp $ 27 */ 28 29 #include <sys/param.h> 30 #include <sys/systm.h> 31 #include <sys/kernel.h> 32 #include <sys/sysproto.h> 33 #include <sys/exec.h> 34 #include <sys/imgact.h> 35 #include <sys/imgact_aout.h> 36 #include <sys/mman.h> 37 #include <sys/proc.h> 38 #include <sys/resourcevar.h> 39 #include <sys/sysent.h> 40 #include <sys/systm.h> 41 #include <sys/vnode.h> 42 #include <sys/inflate.h> 43 44 #include <vm/vm.h> 45 #include <vm/vm_param.h> 46 #include <sys/lock.h> 47 #include <vm/pmap.h> 48 #include <vm/vm_map.h> 49 #include <vm/vm_kern.h> 50 #include <vm/vm_extern.h> 51 52 int 53 exec_resident_imgact(struct image_params *imgp) 54 { 55 struct vmresident *vmres; 56 57 /* 58 * resident image activator 59 */ 60 if ((vmres = imgp->vp->v_resident) == NULL) 61 return(-1); 62 exec_new_vmspace(imgp, vmres->vr_vmspace); 63 imgp->resident = 1; 64 imgp->interpreted = 0; 65 imgp->proc->p_sysent = vmres->vr_sysent; 66 imgp->entry_addr = vmres->vr_entry_addr; 67 return(0); 68 } 69 70 static int exec_res_id; 71 static TAILQ_HEAD(,vmresident) exec_res_list = TAILQ_HEAD_INITIALIZER(exec_res_list); 72 73 static MALLOC_DEFINE(M_EXEC_RES, "vmresident", "resident execs"); 74 75 /* 76 * exec_sys_register(entry) 77 * 78 * Register ourselves for resident execution. Only root can do this. This 79 * will snapshot the vmspace and cause future exec's of the specified binary 80 * to use the snapshot directly rather then load & relocate a new copy. 81 */ 82 int 83 exec_sys_register(struct exec_sys_register_args *uap) 84 { 85 struct vmresident *vmres; 86 struct vnode *vp; 87 struct proc *p; 88 int error; 89 90 p = curproc; 91 if ((error = suser(p->p_thread)) != 0) 92 return(error); 93 if ((vp = p->p_textvp) == NULL) 94 return(ENOENT); 95 if (vp->v_resident) 96 return(EEXIST); 97 vhold(vp); 98 vmres = malloc(sizeof(*vmres), M_EXEC_RES, M_WAITOK); 99 vp->v_resident = vmres; 100 vmres->vr_vnode = vp; 101 vmres->vr_sysent = p->p_sysent; 102 vmres->vr_id = ++exec_res_id; 103 vmres->vr_entry_addr = (intptr_t)uap->entry; 104 vmres->vr_vmspace = vmspace_fork(p->p_vmspace); /* XXX order */ 105 TAILQ_INSERT_TAIL(&exec_res_list, vmres, vr_link); 106 return(0); 107 } 108 109 /* 110 * exec_sys_unregister(id) 111 * 112 * Unregister the specified id. If an id of -1 is used unregister 113 * the registration associated with the current process. An id of -2 114 * unregisters everything. 115 */ 116 int 117 exec_sys_unregister(struct exec_sys_unregister_args *uap) 118 { 119 struct vmresident *vmres; 120 struct proc *p; 121 int error; 122 int id; 123 int count; 124 125 p = curproc; 126 if ((error = suser(p->p_thread)) != 0) 127 return(error); 128 129 /* 130 * If id is -1, unregister ourselves 131 */ 132 if ((id = uap->id) == -1 && p->p_textvp && p->p_textvp->v_resident) 133 id = p->p_textvp->v_resident->vr_id; 134 135 /* 136 * Look for the registration 137 */ 138 error = ENOENT; 139 count = 0; 140 restart: 141 TAILQ_FOREACH(vmres, &exec_res_list, vr_link) { 142 if (id == -2 || vmres->vr_id == id) { 143 TAILQ_REMOVE(&exec_res_list, vmres, vr_link); 144 if (vmres->vr_vnode) { 145 vmres->vr_vnode->v_resident = NULL; 146 vdrop(vmres->vr_vnode); 147 vmres->vr_vnode = NULL; 148 } 149 if (vmres->vr_vmspace) { 150 vmspace_free(vmres->vr_vmspace); 151 vmres->vr_vmspace = NULL; 152 } 153 free(vmres, M_EXEC_RES); 154 error = 0; 155 ++count; 156 goto restart; 157 } 158 } 159 if (error == 0) 160 uap->sysmsg_result = count; 161 return(error); 162 } 163 164