1 /* $NetBSD: procfs_mem.c,v 1.23 1999/03/25 04:45:57 sommerfe Exp $ */ 2 3 /* 4 * Copyright (c) 1993 Jan-Simon Pendry 5 * Copyright (c) 1993 Sean Eric Fagan 6 * Copyright (c) 1993 7 * The Regents of the University of California. All rights reserved. 8 * 9 * This code is derived from software contributed to Berkeley by 10 * Jan-Simon Pendry and Sean Eric Fagan. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Berkeley and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * @(#)procfs_mem.c 8.5 (Berkeley) 6/15/94 41 */ 42 43 /* 44 * This is a lightly hacked and merged version 45 * of sef's pread/pwrite functions 46 */ 47 48 #include <sys/param.h> 49 #include <sys/systm.h> 50 #include <sys/time.h> 51 #include <sys/kernel.h> 52 #include <sys/proc.h> 53 #include <sys/vnode.h> 54 55 #include <miscfs/procfs/procfs.h> 56 57 #include <vm/vm.h> 58 #include <vm/vm_kern.h> 59 #include <vm/vm_page.h> 60 61 #include <uvm/uvm_extern.h> 62 63 #define ISSET(t, f) ((t) & (f)) 64 65 /* 66 * Copy data in and out of the target process. 67 * We do this by mapping the process's page into 68 * the kernel and then doing a uiomove direct 69 * from the kernel address space. 70 */ 71 int 72 procfs_domem(curp, p, pfs, uio) 73 struct proc *curp; /* tracer */ 74 struct proc *p; /* traced */ 75 struct pfsnode *pfs; 76 struct uio *uio; 77 { 78 int error; 79 80 size_t len; 81 vaddr_t addr; 82 83 len = uio->uio_resid; 84 85 if (len == 0) 86 return (0); 87 88 addr = uio->uio_offset; 89 90 if ((error = procfs_checkioperm(curp, p)) != 0) 91 return (error); 92 93 /* XXXCDC: how should locking work here? */ 94 if ((p->p_flag & P_WEXIT) || (p->p_vmspace->vm_refcnt < 1)) 95 return(EFAULT); 96 PHOLD(p); 97 p->p_vmspace->vm_refcnt++; /* XXX */ 98 error = uvm_io(&p->p_vmspace->vm_map, uio); 99 PRELE(p); 100 uvmspace_free(p->p_vmspace); 101 102 #ifdef PMAP_NEED_PROCWR 103 if (uio->uio_rw == UIO_WRITE) 104 pmap_procwr(p, addr, len); 105 #endif 106 return (error); 107 } 108 109 /* 110 * Given process (p), find the vnode from which 111 * it's text segment is being executed. 112 * 113 * It would be nice to grab this information from 114 * the VM system, however, there is no sure-fire 115 * way of doing that. Instead, fork(), exec() and 116 * wait() all maintain the p_textvp field in the 117 * process proc structure which contains a held 118 * reference to the exec'ed vnode. 119 */ 120 struct vnode * 121 procfs_findtextvp(p) 122 struct proc *p; 123 { 124 125 return (p->p_textvp); 126 } 127 128 /* 129 * Ensure that a process has permission to perform I/O on another. 130 * Arguments: 131 * p The process wishing to do the I/O (the tracer). 132 * t The process who's memory/registers will be read/written. 133 */ 134 int 135 procfs_checkioperm(p, t) 136 struct proc *p, *t; 137 { 138 int error; 139 140 /* 141 * You cannot attach to a processes mem/regs if: 142 * 143 * (1) it's not owned by you, or is set-id on exec 144 * (unless you're root), or... 145 */ 146 if ((t->p_cred->p_ruid != p->p_cred->p_ruid || 147 ISSET(t->p_flag, P_SUGID)) && 148 (error = suser(p->p_ucred, &p->p_acflag)) != 0) 149 return (error); 150 151 /* 152 * (2) ...it's init, which controls the security level 153 * of the entire system, and the system was not 154 * compiled with permanetly insecure mode turned on. 155 */ 156 if (t == initproc && securelevel > -1) 157 return (EPERM); 158 159 /* 160 * (3) the tracer is chrooted, and its root directory is 161 * not at or above the root directory of the tracee 162 */ 163 164 if (!proc_isunder(t, p)) 165 return EPERM; 166 167 return (0); 168 } 169 170 #ifdef probably_never 171 /* 172 * Given process (p), find the vnode from which 173 * it's text segment is being mapped. 174 * 175 * (This is here, rather than in procfs_subr in order 176 * to keep all the VM related code in one place.) 177 */ 178 struct vnode * 179 procfs_findtextvp(p) 180 struct proc *p; 181 { 182 int error; 183 vm_object_t object; 184 vaddr_t pageno; /* page number */ 185 186 /* find a vnode pager for the user address space */ 187 188 for (pageno = VM_MIN_ADDRESS; 189 pageno < VM_MAXUSER_ADDRESS; 190 pageno += PAGE_SIZE) { 191 vm_map_t map; 192 vm_map_entry_t out_entry; 193 vm_prot_t out_prot; 194 boolean_t wired, single_use; 195 vaddr_t off; 196 197 map = &p->p_vmspace->vm_map; 198 error = vm_map_lookup(&map, pageno, 199 VM_PROT_READ, 200 &out_entry, &object, &off, &out_prot, 201 &wired, &single_use); 202 203 if (!error) { 204 vm_pager_t pager; 205 206 printf("procfs: found vm object\n"); 207 vm_map_lookup_done(map, out_entry); 208 printf("procfs: vm object = %p\n", object); 209 210 /* 211 * At this point, assuming no errors, object 212 * is the VM object mapping UVA (pageno). 213 * Ensure it has a vnode pager, then grab 214 * the vnode from that pager's handle. 215 */ 216 217 pager = object->pager; 218 printf("procfs: pager = %p\n", pager); 219 if (pager) 220 printf("procfs: found pager, type = %d\n", 221 pager->pg_type); 222 if (pager && pager->pg_type == PG_VNODE) { 223 struct vnode *vp; 224 225 vp = (struct vnode *) pager->pg_handle; 226 printf("procfs: vp = %p\n", vp); 227 return (vp); 228 } 229 } 230 } 231 232 printf("procfs: text object not found\n"); 233 return (0); 234 } 235 #endif /* probably_never */ 236